Javascript 如何理解本承诺执行令?
我不明白为什么这段代码会产生这样的顺序?有人能详细说明一下吗?我认为承诺就像FIFO队列,但嵌套的承诺函数似乎有点不可预测,或者可能使用其他数据结构Javascript 如何理解本承诺执行令?,javascript,promise,Javascript,Promise,我不明白为什么这段代码会产生这样的顺序?有人能详细说明一下吗?我认为承诺就像FIFO队列,但嵌套的承诺函数似乎有点不可预测,或者可能使用其他数据结构 新承诺(解决=>{ 解决() }) .然后(()=>{ 新承诺(解决=>{ 解决() }) .然后(()=>{ 控制台日志(1) }) .然后(()=>{ 控制台日志(2) }) .然后(()=>{ console.log(3.1) }) }) .然后(()=>{ console.log(1.1) 新承诺((解决=>{ 解决() })) .然后(
新承诺(解决=>{
解决()
})
.然后(()=>{
新承诺(解决=>{
解决()
})
.然后(()=>{
控制台日志(1)
})
.然后(()=>{
控制台日志(2)
})
.然后(()=>{
console.log(3.1)
})
})
.然后(()=>{
console.log(1.1)
新承诺((解决=>{
解决()
}))
.然后(()=>{
新承诺(解决=>{
解决()
})
.然后(()=>{
控制台日志(4)
})
.然后(()=>{
控制台日志(6)
})
}).然后(()=>{
控制台日志(5)
})
}).然后(()=>{
控制台日志(3)
})
console.log(0)
承诺是异步的。这意味着每次创建新承诺时,都会启动一个新的异步操作
JS中的异步操作是什么?首先,您需要了解JS在单个线程上运行,无论您做什么。所以,为了让它看起来像是异步的——有一个叫做的东西(从评论到原始帖子的链接,tnx@Taki为伟大的来源)
通常,事件循环存储所有异步函数和主代码操作之间的操作中的“滑动”。这是一个过于简单的解释,请参考链接阅读更多内容,但这就是它的要点
因此,这里基本上没有“FIFO”队列——异步函数的顺序实际上取决于处理器速度、操作系统等因素
但是-有一种方法可以确保一个异步操作只有在另一个异步操作完成后才能执行,这就是.then
子句。问题是,它只确保中的特定函数。然后将在它连接到的特定承诺之后执行
,但它没有说明它在事件循环中相对于其他异步操作(承诺)的顺序。例如,在您的代码中:
new Promise(resolve => {
resolve() // PROMISE A
})
.then(() => {
new Promise(resolve => {
resolve() // PROMISE B
})
.then(() => {
console.log(1) //PROMISE C
})
.then(() => {
console.log(2)
})
.then(() => {
console.log(3.1)
})
})
.then(() => {
console.log(1.1) // PROMISE D
new Promise((resolve => {
resolve()
}))
我参与其中是为了解释:
所以,承诺A首先解决问题。这保证了承诺B将立即解决。当事情变得复杂时:既然承诺B已经解决,承诺C和D现在都进入事件循环!为什么?因为Promise A有2个,然后是子句,所以当第一个结束时-事件循环取第二个,即Promise D。但是第一个。然后子句也有一个。然后他自己的子句-Promise C,它也进入事件循环
承诺D和承诺C之间没有任何联系!它们可以按任何顺序执行。保持这种逻辑,您将看到它在其余的承诺中是如何工作的,而且如果您尝试在不同的操作系统上运行它,那么承诺的顺序可能会有所不同,因为操作系统对于事件循环的实现不同
希望这能帮助你了解一点
免责声明:我在JS方面没有太多经验,但承诺确实吸引了我,所以我对它做了深入的研究。我支持我在这里写的一切,但如果我的解释有任何更正,我很乐意听到
编辑
我下面的答案也是正确的,但没有任何解释,所以让我补充一下:
当您不返回承诺中的任何内容(或.then
子句,该子句也返回承诺)时,它将隐式返回一个已解析的承诺,在超出承诺之前没有任何价值,基本上就像在承诺C中的控制台.log
之后添加return new promise.resolve()
。当这样做时,承诺B之后的所有.then
子句只会在前一个结束后进入事件循环(例如B结束,所以C进入循环,然后进入下一个.then
等等),但在它们之间还有其他承诺或。然后子句(比如承诺D)也可以进入
但是,当您返回包含链接到它的.then
子句的承诺时,它确保整个promise+then子句块按顺序进入事件循环,因此.then
子句也将按您想要的顺序执行:)
tnx@Eugene Sunic感谢您的加入 由于代码中不存在返回,它会导致不可预测的顺序
向承诺中添加回报,您将获得可理解的输出,并且可以轻松跟踪承诺的执行情况
首先,同步0被打印,然后整个第一个承诺块被执行,就像你说的FIFO
1,2,3.1
在此之后,将执行链接表
1.1
之后,打印块4,6
在输出5的链表之后,最后一个链表打印数字3
给我们留下0,1,2,3.1,1.1,4,6,5,3
newpromise(resolve=>resolve())
.然后(()=>{
返回新承诺(resolve=>resolve())
.然后(()=>console.log(1))
.然后(()=>console.log(2))
.然后(()=>console.log(3.1));
})
.然后(()=>{
控制台日志(1.1);
返回新承诺((resolve=>resolve())
.然后(()=>{
返回新承诺((resolve)=>resolve())
.然后(()=>console.log(4))
.然后(()=>console.log(6))
}).然后(()=>console.log(5))
}).然后(()=>console.log(3))
console.log(0)
它是FIFO,执行如下:
main [4] logs: 0 // main code executed, one executor added to FIFO (4)
4 [8,18] // executor at line 4 runs, two executors added to FIFO (8, 18)
8 [18,11] logs: 1 // etc etc
18 [11,23,36] logs: 1.1
11 [23,36,14] logs: 2
23 [36,14,27,33]
36 [14,27,33] logs: 3
14 [27,33] logs: 3.1
27 [33,30] logs: 4
33 [30] logs: 5
30 logs: 6
正如您所看到的,它的先进先出顺序是:[4,8,18,11,23,36,14,27,33,30]
,但它存储的是执行者(对履行或拒绝的承诺的回调),而不是承诺。换句话说:承诺履行或拒绝的时间决定其何时添加到FIFO,而不是承诺创建的时间。您会选择什么顺序