Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/396.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 为什么这个异步函数要在等价的Promise.chain之前执行呢?_Javascript_Promise_Async Await_Es6 Promise - Fatal编程技术网

Javascript 为什么这个异步函数要在等价的Promise.chain之前执行呢?

Javascript 为什么这个异步函数要在等价的Promise.chain之前执行呢?,javascript,promise,async-await,es6-promise,Javascript,Promise,Async Await,Es6 Promise,我有以下代码: var incr=num=>新承诺(解析=>{ 解析(num+1); }); 变量x=增量(3) .然后(resp=>incr(resp)) 。然后(resp=>console.log(resp)); 异步函数incrTwice(num){ const first=等待增量(num); 常数两次=等待增量(第一次); console.log(两次); } 增加(6)你的想法是可以理解的,符合逻辑的。观察到的行为的原因与Promise API中内置的保证之一有关,即承诺在执行时始

我有以下代码:

var incr=num=>新承诺(解析=>{
解析(num+1);
});
变量x=增量(3)
.然后(resp=>incr(resp))
。然后(resp=>console.log(resp));
异步函数incrTwice(num){
const first=等待增量(num);
常数两次=等待增量(第一次);
console.log(两次);
}

增加(6)你的想法是可以理解的,符合逻辑的。观察到的行为的原因与Promise API中内置的保证之一有关,即承诺在执行时始终是异步的,即使它们执行同步操作(如立即解析承诺)。更严格地说,这意味着在当前运行完成之前,永远不会调用承诺的回调

作为MDN:

在JavaScript事件循环结束之前,永远不会调用回调

因此:


我会在我的承诺指南中介绍这一点。首先,让我指出,你永远不应该争论独立承诺链的执行顺序。有两个异步调用,它们互不依赖,而是并发运行,因此应始终期望它们以任意顺序完成

仅使用立即解析承诺的玩具示例使此顺序依赖于微任务队列语义,而不是实际的异步任务,这使得这纯粹是一个学术练习(其在规范中)

无论如何,让我们澄清一下你的误解:

在声明
x
incrTwice
之间,堆栈为空,这将导致刷新微任务队列

否,只有在所有用户代码运行完成后,堆栈才会变为空。堆栈上仍然有
元素的全局执行上下文。在所有同步代码(
incr=…
x=incr(3)…
incrTwice(6)
)完成之前,不会执行任何微任务

我相信[代码]展示了两种实现相同功能的等效方法:第一种是通过链接承诺,第二种是使用async/await的语法糖

不完全是。当取消测试从第一个
然后(…)
处理程序返回的
incr(resp)
承诺时,
.then()
链接还有一个额外的解析步骤。要使其行为与
incrTwice
中的
wait
ed承诺完全相同,您需要编写

incr(3).then(resp =>
  incr(resp).then(resp =>
    console.log(resp)
  )
);
如果您这样做,您将按照启动两个承诺链的顺序获得
控制台
日志,因为在执行
控制台.log()
之前,它们将执行相同数量的微任务


有关更多详细信息,请参见,,

是,但在我的示例中,两个“版本”都是承诺。我知道承诺将在同一脚本中的任何同步代码之后解析,就像承诺将微任务排队一样,直到堆栈清空后才会刷新。我感兴趣的是微任务队列中两个承诺之间的交错,而不是一个承诺和一段同步代码之间的交错。
incr(3).then(resp =>
  incr(resp).then(resp =>
    console.log(resp)
  )
);