Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在承诺中解决承诺的顺序_Javascript_Promise - Fatal编程技术网

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()
    将处理程序回调添加到队列中运行
  • 如果步骤4和6中的这两个
    .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')
    });