![](/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.