Infinite asyncIterator未能按预期工作

问题描述 投票:0回答:1

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

在节点v12.14.0上与ts节点一起运行。

 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);
})();
javascript node.js typescript asynchronous
1个回答
0
投票

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

只要存在已解决的承诺和遵循它的链,该过程将继续运行。由于您在s.send()之前多次调用for await,因此循环中的前两次迭代已解决了promise,因此需要运行更多代码。此后,它等待一个未解决的承诺,这使您对(async () => { ... })()的呼叫成为一个未解决的承诺。在没有其他代码运行的情况下,该过程退出。

要解决此问题,您可以执行setInterval(() => {}, Number.MAX_VALUE)之类的讨厌的操作。只要计划了超时,该过程就不会退出。

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

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,然后退出。

© www.soinside.com 2019 - 2024. All rights reserved.