了解是什么触发移动到 javascript 承诺链的下一个 .then()

Understanding what triggers moving to the next .then() of a javascript promise chain

我有一个看起来像这样的承诺链。

fistAsyncFunction()
    .then(() => {
        secondAsyncFunction()
    })
    .then(() => {
        thirdAsyncFunction()
    })

我注意到第三个异步函数在第二个异步函数完成之前开始,但在将其更改为这个之后,它按照我想要的方式运行。

fistAsyncFunction()
    .then(() => {
        return secondAsyncFunction()
    })
    .then(() => {
        thirdAsyncFunction()
    })

似乎即使第二个异步函数没有 return 任何东西,程序也会等待它 return undefined 然后再进行下一个承诺。这是实际发生的事情吗?如果不是,那么提示 javascript 开始执行下一个承诺的幕后发生了什么?

当你有这样的承诺链时:

fn1().then(() => {
    fn2();
}).then(() => {
    fn3();
});

事件顺序如下:

  1. fn1() 执行并且 return 是一个承诺(我会调用 p1)。
  2. 使用 returned promise p1,调用 .then() 方法,该方法仅存储回调并立即 return 另一个 promise p2
  3. 使用 returned promise p2,调用 .then() 方法,该方法简单地存储回调并立即 return 另一个 promise p3(不会被任何东西保存或使用)。
  4. 稍后 p1 解决。这会导致调用先前保存的 .then() 处理程序。
  5. .then() 处理程序 运行 是其中的代码。在此特定示例中,这调用 fn2()。但是,由于 fn2() 也是异步的,它只是开始其操作并立即 return 是一个承诺。但是,在这个特定的代码示例中,没有任何东西在查看 returned promise,因此它没有被使用。然后,从 .then() 处理程序执行 returns 回到最初调用它的承诺。该承诺查看来自 .then() 处理程序的 return 值并找到它 undefined。由于这里没有额外的 promise 需要等待,因此它会解析自己的 promise p2.
  6. 解析 p2 后,它会调用其 .then() 处理程序,该处理程序启动 fn3()。现在,您将同时拥有 fn2()fn3(),并且不确定哪个先完成(这实际上只是两个异步操作之间的竞赛)。

当你改为这样做时:

fn1().then(() => {
    return fn2();
}).then(() => {
    return fn3();
});

然后,在第 5 步之前一切都是一样的。但是,在本示例的第 5 步中,第一个 .then() 处理程序执行 return fn2()。因此,fn2() 就像前面的示例一样被调用,它 return 是一个承诺,并且该承诺是 return 来自 .then() 处理程序的。这告诉宿主 promise 它需要等到那个 promise 也解决了才能继续 promise 链。

因此,如果您 运行 在 .then() 处理程序中进行异步操作并且您希望承诺链等待它们,则必须 return 来自 [=15] 的承诺=] 链接到您的内部异步操作的处理程序。如果你不这样做,那么那些额外的异步操作只是 "fire and forget" 因为没有人关注它们何时完成或是否有错误。

这样想

fistAsyncFunction()
    .then(() => {
        secondAsyncFunction()
        return undefined
    })
    .then((iAmUndefined) => {
        thirdAsyncFunction()
        return undefined
    })

^ 这是您第一个带有显式 returns 的示例。

It seems like even though the second async function didn't return anything, the program waited for it to return undefined before moving onto the next promise.

所以你在这方面是对的。第二个异步函数没有 return 任何东西;那是对的。但是,该程序不会等待 secondAsyncFunction() 到 return 未定义。此外,它根本不等待 secondAsyncFunction()。相反,您的程序说

Okay secondAsyncFunction I will now call you and let you run away; I will not wait for you. Instead I'm just going to return undefined and move on. Hello thirdAsyncFunction!

您注意到 thirdAsyncFunctionsecondAsyncFunction returned 之前启动是正确的。

接下来,您修改了代码以实现预期的行为

fistAsyncFunction()
    .then(() => {
        return secondAsyncFunction()
    })
    .then(resultOfSecondAsyncFunction => {
        thirdAsyncFunction()
        return undefined
    })

^ 这是你的第二个带有显式 returns

的例子

您的程序现在按照您希望的方式运行,因为通过 returning secondAsyncFunction(),您现在正在指示您的程序等待该函数的 return。

what is going on under the hood that prompts javascript to start executing the next promise?

在幕后,Promise 构造函数中使用了一个特殊函数 resolve。当调用前一个承诺的 resolve 函数时,下一个承诺将开始执行。当然,两个 promise 必须通过 .then.

联系在一起