【问题标题】:Async function never returns while waiting for a nested Promise to fulfill在等待嵌套的 Promise 完成时,异步函数永远不会返回
【发布时间】:2018-04-04 21:35:30
【问题描述】:

在下面的代码中有一个outer 函数和一个inner 函数。 outer 应该是 await inner 并在完成时返回。 inner 返回一个 Promise,它在超时后完成。我希望outer 函数在此Promise 完成后立即返回:

const outer = async () => {
    let counter = 0;
    const inner = async () => {
        console.log('inner');
        return new Promise((fulfill, reject) => {
            if (++counter === 3) {
                console.log('fulfill');
                fulfill();
                return;
            }
            setTimeout(() => inner(), 1000);
        });
    };
    return await inner();
};
outer().then(() => console.log('outer done'));

outer 永远不会完成。注意没有outer done输出:

inner
inner
inner
fulfill

在以下代码中,outer 完成。它本身返回一个Promiseinner 函数实现了它:

const outer = async () => {
    return new Promise((fulfill, reject) => {
        let counter = 0;
        const inner = async () => {
            console.log('inner');
            if (++counter === 3) {
                console.log('fulfill');
                fulfill();
                return;
            }
            setTimeout(() => inner(), 1000);
        };
        inner().catch(err => reject(err));
    });
};
outer().then(() => console.log('outer done'));

输出:

inner
inner
inner
fulfill
outer done

我认为这两种情况下的行为应该是相似的。任何人都可以看到并解释其中的区别吗?

【问题讨论】:

    标签: javascript node.js asynchronous promise async-await


    【解决方案1】:

    您从未在inner 中调用过fullfill 函数。你创建了一堆新的 Promise,你只告诉了最后一个 Promise 它已经解决了。

    让我们看看你的异步任务:

    {
        if (++counter === 3) {
            console.log('fulfill');
            fulfill();
            return;
        }
        setTimeout(() => inner(), 1000);
    }
    

    在第一次调用inner,即这部分:

    return await inner();
    

    counter 为 0。这意味着整个 if 块没有被执行。在其余代码中,它从未调用过fulfill 函数,因此promise 从未得到解决。

    如果您的生产代码库中存在此代码(或这种代码风格),我的建议是您应该重写它。

    要修复它真的很快你可以这样做:

    setTimeout(() => inner().then(() => fulfill()), 1000);
    

    Demo

    【讨论】:

    • 你如何解释这种情况下fulfilllog 的存在?它证明代码到达了那个点。
    • @YuryFedorov 你完成了最后一个承诺,但不要忘记你已经创建了 四个 个新的承诺。日志实际上证明它 没有 没有到达它,因为应该有 4 行而不是 1 行。
    猜你喜欢
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 2015-08-15
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    相关资源
    最近更新 更多