如何通过 Deno 中的工作程序将 stdout/stderr 传输到文件?

wca*_*art 5 javascript deno

假设我有以下代码片段来在 Deno 中创建一个工作线程并启动它。

const worker = new Worker("./worker.ts", { type: "module", deno: true });
worker.postMessage({ command: "START" });
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以将 stdout/stderr 从工作程序传输到文件,类似于Deno.run工作原理?例如,这样的事情可能吗?

const file = await Deno.open('/path/to/file.log', { write: true });
const worker = new Worker("./worker.ts", {
  type: "module",
  deno: true,
  stdout: file.rid,
  stderr: file.rid
});
worker.postMessage({ command: "START" });
Run Code Online (Sandbox Code Playgroud)

或者,是否可以使用流?

import { WritableStream } from "https://denopkg.com/keroxp/deno-streams/writable_stream.ts"
const stream = new WritableStream<number>({
    write: chunk => {
        ...
    }
})
const worker = new Worker("./worker.ts", {
  type: "module",
  deno: true,
  stdout: stream,
  stderr: stream
});
worker.postMessage({ command: "START" });
Run Code Online (Sandbox Code Playgroud)

Mar*_*nde 1

目前不支持传输流:

https://github.com/whatwg/streams/blob/main/transferable-streams-explainer.md

一旦完成,您将能够使用以下语法将WritableStream//传输ReadableStream到工作线程。TransformStream

const ws = new WritableStream({
  // implement
});
worker.postMessage(ws, [ws]);
Run Code Online (Sandbox Code Playgroud)

作为临时解决方案,在支持之前,可以使用&MessageChannel来表示stdoutstderr

主要的

const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
  type: "module",
  deno: true
});

const stdout = new MessageChannel();
const stderr = new MessageChannel();

worker.postMessage({ command: 'stdout' }, [stdout.port1])
worker.postMessage({ command: 'stderr' }, [stderr.port1])
worker.postMessage({ command: "START" });

stdout.port2.onmessage = (stderr) => {
    // write to your stream, or whatever you need
    console.log('stdout:', stderr.data);
}
stderr.port2.onmessage = (stderr) => {
    console.log('stderr:', stderr.data);
}

worker.onmessage = (e) => {
    console.log('onMessage: Message received from worker');
}
Run Code Online (Sandbox Code Playgroud)

工人

let stdout;
let stderr;

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function start() {
    while(true) {
        await delay(1000);
        stdout.postMessage(`some data: ${new Date()}`);
        stderr.postMessage(new Error('foo'));

        self.postMessage('other messages');
    }
}

self.onmessage = (evt) => {
    if(evt.data.command === 'stdout')
        [stdout] = evt.ports;
    else if(evt.data.command === 'stderr')
        [stderr] = evt.ports;
    else if(evt.data.command === 'START')
        start();
};
Run Code Online (Sandbox Code Playgroud)