簡體   English   中英

如何在保留順序的同時異步處理 Node.js 中的 stream 事件?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM