以下代码的实际输出(在Firefox控制台中显示)为 -错误1 -错误2 -继续1 -继续3。
Promise
.resolve()
.then(() => Promise.reject('error1'))
.catch(console.log)
.then(() => console.log('continue1'))
Promise
.resolve()
.then(() => Promise.reject('error2'))
.then(() => console.log('continue2'), console.log)
.then(() => console.log('continue3'))
据我对诺言的理解,应该是-错误1-继续1-错误2-继续3。
需要帮助来了解实际输出
答案 0 :(得分:4)
首先,试图理解两个完全独立的promise链之间可能存在的排序问题是毫无意义的。进行编程时,应将它们的顺序视为不确定的(实际上,一旦在任何真实的promise链实现通常包含的promise链中有真正的异步操作,该顺序就会变得不确定)。如果两个链之间的顺序对您很重要,那么您需要添加一些特定的代码来协调两个独立的Promise链的动作。
因此,您在代码段中观察到的顺序是:
error1
error2
continue1
continue3
由于在任何.then()
或.catch()
处理程序中都没有异步操作,因此它将简单地在两个Promise链之间交替(这是运行代码段时的工作) 。基本上是这样执行的:
Promise.resolve()
,这会在事件队列中添加一个事件,以运行其.then()
处理程序。Promise.resolve()
,这会向事件队列添加一个事件,以运行其.then()
处理程序。.then()
处理程序,然后将另一个事件插入事件队列以运行.catch()
处理程序并将控制权返回到事件循环。.then()
处理程序位于事件队列的顶部并开始运行请记住,根据promise规范,每个连续的.then()
或.catch()
处理程序都必须异步运行(在事件队列的下一轮)。诺言链没有尽其所能。它执行下一步,将其后的步骤放入队列,然后将控制权返回给事件循环,该事件循环将下一个事件弹出队列。这将导致控件在不同的promise链之间轮换,这些promise链不需要等待其他事情完成。
但是,我重复一遍,您不应该依赖于此执行顺序级别,并且在涉及其他异步操作的更复杂的实际情况下,您不能尝试预测顺序。您应该假设这两个单独的承诺链以不确定的顺序运行,超出了同步部分(每个Promise.resolve()
)。然后,如果您的代码有任何特定的排序问题,则必须添加代码以使用Promise.all()
来实际同步和控制执行顺序,或将这些链链接在一起成为一个分支链或一个序列链,或者取决于代码的需求。
答案 1 :(得分:1)
解决/拒绝的承诺将微任务放入相应的队列中。该任务涉及调用任何then
/ catch
回调函数。该队列中的消息将按顺序处理。
所以在您的示例中,顺序为:
首先执行Promise.resolve()
。微任务队列现在有1个条目:
正常执行流程继续到第二个Promise.resolve()
第二个Promise.resolve()
被执行。现在,微任务队列有2个条目:
正常执行流程结束-调用堆栈为空。
提取并处理队列中的第一项。 then
回调() => Promise.reject('error1')
被执行。这会创建一个新的,被拒绝的承诺,因此将拒绝添加到队列中
提取并处理队列中的第一项。 then
回调() => Promise.reject('error2')
被执行。这会创建一个新的,被拒绝的承诺,因此将拒绝添加到队列中
提取并处理队列中的第一项。这是拒绝,因此执行了catch
回调console.log
。这将输出“ error1”并创建一个新的,已解决的承诺(具有未定义的值)。队列
...等等
答案 2 :(得分:0)
我不确定在任何地方都指定了不相关的Promise的确切执行顺序,即使这样,如果这对您很重要,您可能想在这两个Promise之间引入一些显式的顺序依赖关系。
但这是一种可能的可能性序列:
then
。这导致两者均被拒绝。我不会依赖于这两个相对于彼此执行的顺序。catch/then
。我不会依赖于这两个相对于彼此执行的顺序。您可以大概可以按顺序执行这些步骤(因为它遵循将这些回调提交给调度程序的排队顺序),但这看起来还是有风险的。
如果要让continue1
发生在error2
之前,则必须安排等待前者完成的代码。