微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript-异步函数永远不会在等待嵌套的Promise完成时返回

在下面的代码中,有一个外部函数一个内部函数.外部应该等待内部,并在完成时返回.内部返回一个Promise,该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'));

外部永远不会完成.请注意,没有外部完成输出

inner
inner
inner
fulfill

在下面的代码中外部完成.它返回一个Promise本身,并且内部函数实现它:

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

我认为这两种情况下的行为应相似.有人可以看到并解释差异吗?

解决方法:

您从未在inner中调用过fullfill函数.您创建了一堆新的Promises,但您只告诉最后一个承诺,该承诺已解决.

让我们来看看您的异步任务:

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

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

return await inner();

计数器为0.这意味着未执行整个if块.在代码的其余部分中,它从未调用过fulfill函数,因此promise也从未得到解决.

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

要非常快地修复它,您可以执行以下操作:

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

Demo

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐