繁体   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