【问题标题】:Infinite asyncIterator is not working as expected无限 asyncIterator 未按预期工作
【发布时间】:2020-04-26 05:26:56
【问题描述】:

所以我正在尝试创建一个无限的 asyncIterator / 生成器。 该代码应该为“for await of”循环产生“Hello”和“Hi”,然后永远等待下一个值。问题是它不会等待第三个值,也不会在循环后打印 2 并且没有错误地终止。

在节点 v12.14.0 上使用 ts-node 运行。

 class Source<T> {

    _data: T[] = [];
    _queue: ((val: T) => void)[] = [];

    send(val: T) {
        if (this._queue.length > 0) {
            this._queue.shift()!(val);
        } else {
            this._data.push(val);
        }
    }

    next(): Promise<{ done: boolean, value: T }> {
        return new Promise((resolve, _reject) => {
            if (this._data.length > 0) {
                resolve({ done: false, value: this._data.shift()! });
            } else {
                this._queue.push(value => resolve({ done: false, value }));
            }
        });
    }

    [Symbol.asyncIterator]() {
        return this;
    }

}

(async () => {
    const s = new Source<String>();
    s.send("Hello");
    s.send("Hi");

    console.log(1);

    for await (let str of s) {
        console.log(str);
    }

    console.log(2);
})();

【问题讨论】:

  • 你可以把编译好的js在调试器中单步调试。
  • 嗯,我就是这么做的(使用调试器逐步完成)。我无法解释这种行为。 ??????
  • 看起来未解决的承诺不会阻止程序退出。 new Promise(() =&gt; {}).then(() =&gt; console.log('foo')); 立即退出。我觉得奇怪的是,只要你继续调用s.send(),程序就会一直运行。也许这是因为一旦你调用s.send(),队列中的一个 Promise 就会解析,所以程序有更多的代码要运行?
  • 它不等待第三个值”是什么意思?您的代码中没有第三个值。

标签: javascript node.js typescript asynchronous


【解决方案1】:

Unresolved 承诺不会阻止退出进程。看看this

只要有一个已解决的 Promise 和一个跟随它的链,进程就会继续运行。由于您在for await 之前调用了几次s.send(),因此循环中的前两次迭代已经解决了promise,因此需要运行更多代码。在此之后,它正在等待一个未解决的承诺,这使您对(async () =&gt; { ... })() 的调用成为一个未解决的承诺。没有更多代码运行,进程退出。

为了解决这个问题,你可以做一些讨厌的事情,比如setInterval(() =&gt; {}, 999999999)。只要安排了超时,进程就不会退出。

我花了一段时间才弄清楚在什么情况下我们会想要这种行为——而不是等到所有的承诺都被解决或被拒绝后再退出。

let p1 = Promise.resolve(1),
    p2 = new Promise(() => {}).then(Promise.resolve(2)),
    p3 = Promise.race([p1, p2]).then(console.log);

p2 永远不会解决,p3Promise.race() 调用不会取消 p2then()。但是,我们希望该程序打印 1 然后退出。

【讨论】:

  • (async () =&gt; { setInterval(() =&gt; {}, 999999); ... } 解决了问题
猜你喜欢
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2021-06-04
  • 2022-01-24
相关资源
最近更新 更多