Promise.resolve(1)
.then(x => console.log(1))
.catch(x => console.log(2))
.then(x => console.log(3))
Promise.reject(2)
.then(x => console.log(4))
.catch(x => console.log(6))
.then(x => console.log(7))
结果是“1 6 3 7”,但如果我在catch之前添加另一个then()console.log(6),结果将是1 3 6 7,我不明白为什么
Promise.resolve(1)
.then(x => console.log(1))
.catch(x => console.log(2))
.then(x => console.log(3))
Promise.reject(2)
.then(x => console.log(4))
.then(x => console.log(5))
.catch(x => console.log(6))
.then(x => console.log(7))
结果为1 3 6 7
我想知道它是怎么运作的
2条答案
按热度按时间rqenqsqc1#
Promise侦听器由Promise任务运行器作业在Promise已实现或被拒绝时运行。HTML 5使用微任务队列作为Promise Job队列,队列作为FIFO(先进先出)运行。
在其他JavaScript返回到事件循环之后,Promise Job连续运行,直到Promise Job队列为空。
promise作业的目的是将创建作业的promise的值或拒绝原因传递到promise链中的下一个promise。
如果生成作业的promise被满足,下一个promise将以相同的值被满足,如果被拒绝,则以相同的原因被拒绝。如果一个promise监听器返回一个promise,那么下一个promise将使用返回的promise进行解析。
将promise状态和值传递给下一个promise是使用内部存储的
resolve
和reject
函数的¹值来执行的。值得注意的是,
catch
子句是then
的两个参数调用的简写²。无论源代码中的子句是then
还是catch
,都仍然会创建promise作业来解析、实现或拒绝子句返回的promise对象。将所有这些放在一起,应该可以预测在同时处理多个promise链的情况下promise侦听器执行的顺序。
第一个示例按以下顺序将promise作业相互啮合:
1.不是log(2),而是log 6
第二个示例也使程序作业相互啮合,但具有不同的对齐:
1.非log(2),非log(5)
1.日志(7)
故事的寓意?不要依赖于promise队列中多个作业的执行顺序,如果需要部分完成结果,可以将promise链分成更小的链。
¹关于链式promise的
resolve
和reject
函数。resolve
和reject
函数,用于调用then
、catch
和finally
方法返回的Promise。²关于带一个参数的
then
调用then(listenerFunction)
相当于then(listenerFunction, null)
。如果将null
作为rejection handler应用于一个被拒绝的promise,则会导致链中的下一个promise以相同的原因被拒绝。catch(listenerFunction)
相当于then(null, listenerFunction)
。应用于一个已实现的promise,null
作为fulfillment处理程序会导致链中的下一个promise以相同的值实现。不适用于链中前一个promise的稳定状态的Promise链子句不跳过-它们主动将前一个promise的状态和值传递到为此目的而进入微任务队列的promise作业中的下一个promise。
qvtsj1bj2#
您第一次调用了
Promise.resolve
,因此将调用then
回调。任何后续的then
回调也将被调用。接下来,您调用了
Promise.reject
,这意味着每个then
回调都将被忽略,直到catch
回调(拒绝处理程序)。但是,一旦catch
处理程序完成解析(或完成返回某些内容),如果它没有抛出错误,则会调用下一个then
回调。