Javascript 在承诺中解决承诺的顺序
对于下面的代码Javascript 在承诺中解决承诺的顺序,javascript,promise,Javascript,Promise,对于下面的代码 function inner () { new Promise(function(resolve,reject){ resolve() }).then(function(){ console.log('Inner Promise') }) } function outer() { return new Promise(function(resolve, reject){ resolve() inner() }) } outer
function inner () {
new Promise(function(resolve,reject){
resolve()
}).then(function(){
console.log('Inner Promise')
})
}
function outer() {
return new Promise(function(resolve, reject){
resolve()
inner()
})
}
outer().then(function(data) {
console.log('Outer Promise')
})
输出是
Inner Promise
Outer Promise
我认为外部解析将首先进入JS消息队列,然后是内部解析。
然而,JS事件循环首先触发内部解析,然后触发外部解析
Promise resolve在内部做什么?简而言之,您会看到这样的行为,因为
内部()
Promise上的.then()
方法在外部()
Promise上首先运行,然后外部()
Promise上的方法首先运行,因此它的处理程序首先排队(请参阅下面的逐步解释以了解原因)
Promise resolve在内部做什么
resolve()
将承诺的内部状态更改为已履行。此时,如果有任何.then()
处理程序已附加到promise,则它们将添加到队列中,待堆栈展开且Javascript的当前运行路径完成并将控制权返回给系统时执行。注意,正如您在本例中所看到的(当您阅读下面的分步分析时),如果尚未注册任何。then()
处理程序,则无法将任何内容添加到队列中
我认为外部解析将是第一个输入JS消息的
队列,后跟内部解析。但是,JS事件循环会触发
首先是内部解析,然后是外部解析
承诺解析操作未添加到队列中<代码>解析()
是同步的。它会立即将当前承诺的状态更改为已履行状态。如果在解析承诺时,有任何.then()
处理程序已经注册,那么它们就是添加到队列中的处理程序。但是,在您的两个承诺中,当您的每一个承诺都得到解决时,还没有附加任何.then()
处理程序。因此,这些.then()
处理程序不会在承诺解决时排队。相反,当.then()
方法实际运行并注册它们时,它们将被排队
下面是对代码运行方式的一些分析和可能的解释:
outer()
。这将创建一个Promise对象,并在传递它时同步调用Promise executor回调李>
resolve()
,它将对当前连接的.then()
处理程序的调用进行排队。请注意,在调用resolve()
的那一刻,还没有.then()
处理程序,因为在这个代码outer().then()
中,您仍然在运行outer()
和.then()
,因为它还没有运行,所以实际上还没有任何东西可以排队(这可能是您观察到的顺序的关键-请继续阅读以了解更多详细信息)internal()
。这将创建一个新的承诺,然后(仍然同步运行)调用您传递到那里的承诺执行器回调,该回调调用resolve()
。同样,还没有附加任何.Then()
处理程序,因此仍然没有其他要安排的后续执行internal()
中的Promise executor返回,.then()
方法在internal()
中的Promise上被调用。这个Promise已经被解析了,所以当调用This.then()
处理程序时,Promise知道将它安排在将来运行。因为所有.then()
当堆栈仅展开为平台代码时,将异步调用处理程序,它不会立即运行,但计划在将来通过将其放入队列来运行。这完全取决于此队列的工作方式(宏任务或微任务等),但我们知道Promise规范保证在正在执行的当前同步JS代码段完成运行并将控制返回系统后运行internal()
返回(代码仍在同步运行)outer()
返回,outer().then()
中的.then()
方法运行。就像在上一个示例中一样,当调用this.then()
方法时,主机承诺已经被解析。因此,承诺引擎将调度。then()
将处理程序回调添加到队列中运行.then()
处理程序按运行顺序排队(这将是逻辑实现),那么您将看到上的.then()
处理程序首先运行内部()
上的处理程序,然后外部()
上的处理程序将从内部()开始运行。然后()首先在
outer()之前运行,然后运行()`。这就是您观察到的结果
outer()
之前解析了internal()
,但在解析outer()
时,没有附加.then()
处理程序,因此在解析时没有任何计划供将来执行。这可能就是为什么即使先解析它,它的然后()
处理程序不会首先运行。一旦内部()
和外部()
都得到解决,则是内部的。然后()
方法首先运行,因此它首先在调度处理程序时遇到问题。然后()
处理程序运行,这就是您观察到的情况如果您想更明确地指定内部
.then()
处理程序将首先启动,您可以简单地将其链接到外部()
承诺,如下所示:
函数内部(){
返回新承诺(功能(解决、拒绝){
解决();
}).然后(函数(){
console.log(“内部承诺”)
})
}
函数外部(){
//在此处添加return以链接内部promis
var outer = Promise.resolve();
var inner = Promise.resolve();
inner.then(function() {
console.log('Inner Promise')
});
outer.then(function(data) {
console.log('Outer Promise')
});