![](/img/trans.png)
[英]How to make concurrent Node.js stream processing while preserving order?
[英]How can I asynchronously handle stream events in Node.js while preserving order?
我有一个 stream 有一些事件:
responseStream.on('end', resolve)
responseStream.on('error', reject)
responseStream.on('data', doStuff)
和
const doStuff = async (chunk) => {
return await new Promise((resolve) => setTimeout(() => {
console.log(chunk.toString())
resolve()
}, Math.random() * 1000))
}
我想要做的是保持事件发出的顺序。但这不会发生,因为处理程序需要不同的时间。 保持发出事件顺序的最佳方法是什么?
您将需要一个异步感知队列或 promise 链,以便在事件进入时对它们进行排队并保持它们,直到之前的异步事件处理程序完成。 我开始将它作为一个队列来实现,但后来决定 promise 链可能更容易。
以下是如何做到这一点的想法:
class eventQueue {
constructor(emitter, errorHandler) {
this.emitter = emitter;
this.errorHandler = errorHandler;
this.chain = Promise.resolve();
this.err = null;
this.emitter.on('error', this.processError.bind(this));
}
processError(err) {
// only ever call the errorHandler once
if (this.err) return;
this.err = err;
this.errorHandler(err);
}
on(event, handler) {
this.emitter.on(event, (...args) => {
// wait for previous events to be done before running this one
// and put the new end of the chain in this.chain
this.chain = this.chain.then(() => {
// skip any queued handlers once we've received an error
if (this.err) return;
// now that the chain has gotten to us, call our event handler
return handler(...args);
}).catch(err => {
this.processError(err);
throw err;
});
});
return this;
}
}
每个传入事件都添加到 promise 链中,并且在所有先前的事件都解决了它们返回的任何 promise 之前不会被执行。
然后,在您的伪代码中,您将执行以下操作:
let queue = new eventQueue(responseStream, reject);
queue.on('end', resolve);
queue.on('data', doStuff);
const doStuff = (chunk) => {
return new Promise((resolve) => setTimeout(() => {
console.log(chunk.toString())
resolve()
}, Math.random() * 1000))
}
请注意,eventQueue 已经有一个内置的error
事件侦听器,因此您不需要显式设置一个。 它会调用你传递给构造函数的errorHandler。 任何拒绝的 promise 也会导致调用相同的 errorHandler。 一旦调用了 errorHandler,就不会再调用事件处理程序了。 队列将被锁定在错误 state 中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.