Javascript “与”的区别是什么;事件循环队列“;及;作业队列;?

Javascript “与”的区别是什么;事件循环队列“;及;作业队列;?,javascript,es6-promise,event-loop,job-queue,Javascript,Es6 Promise,Event Loop,Job Queue,我无法理解下面的代码是如何运行的。为什么“1”在“b”之后,而“h”在“3”之后?顺序应该是:a,b,1,2,h,3?一些文章说,“事件循环队列”和“作业队列”之间的差异导致以下输出。但是怎么做呢?我读过的说明书,想知道Promise的工作原理,但它让我更加困惑。有人能帮我吗?谢谢大家! var promise = new Promise(function(resolve, reject) {resolve(1)}); promise.then(function(resolve) {consol

我无法理解下面的代码是如何运行的。为什么“1”在“b”之后,而“h”在“3”之后?顺序应该是:a,b,1,2,h,3?一些文章说,“事件循环队列”和“作业队列”之间的差异导致以下输出。但是怎么做呢?我读过的说明书,想知道Promise的工作原理,但它让我更加困惑。有人能帮我吗?谢谢大家!

var promise = new Promise(function(resolve, reject) {resolve(1)});
promise.then(function(resolve) {console.log(1)});
console.log('a');
promise.then(function(resolve) {console.log(2);});
setTimeout(function() {console.log('h')}, 0);
promise.then(function(resolve) {console.log(3)});
console.log('b');

// a
// b
// 1
// 2
// 3
// h
我知道Promise是异步的,但是setTimeout(..)异步操作的回调总是在Promise的异步操作之后。为什么?

为什么“1”在“b”之后

根据promise规范,在JS的当前线程运行完成后,将异步调用所有promise
.then()
处理程序。因此,作为当前JS的一部分同步执行的
a
b
都将在任何
处理程序之前执行。然后()
处理程序因此
1
将始终在
a
b
之后执行

一些有趣的读物:T和


这里有一些好的建议:

我不建议依赖于具体的执行顺序 非链接事件。如果要控制执行顺序- 以某种方式重新安排回调,以便 以后执行取决于要执行的操作 或者实现一个队列(在引擎盖后面执行相同的操作)

换句话说,如果您依赖于异步事件的特定计时,那么您实际上应该在代码中链接它们,以便通过代码一个接一个地发生,而不是依赖于实现中未指定的调度。

在HTML术语中,来自同一域的一个页面或一组页面的。来自同一个队列的任务始终进入同一队列,由浏览器选择下一个要使用的任务队列

要运行计时器回调的任务来自,并在同一队列中执行。让我们将此队列称为任务队列“A”

ECMAscript 2015(ES6)规范要求任务运行承诺反应回调,以形成自己的作业队列。ECMAscript和HTML规范不使用相同的语言,因此让我们将ECMA的“承诺作业队列”等同于浏览器中的HTML任务队列“B”——至少与计时器使用的队列不同

理论上,浏览器可以从队列a或队列B中选择要运行的任务,但实际上,promise任务队列获得更高的优先级,并在运行计时器回调之前清空

这就是为什么“h”最后被记录的原因。Promise
然后
对已实现承诺的调用将作业放入承诺队列中,其执行优先级高于计时器回调。承诺队列仅在执行
console.log(3)
后变为空,这允许执行计时器回调


高级

ECMAScript守护者选择在他们的规范中不使用HTML5术语或任务队列描述,因为ECMAScript可以运行在比HTML浏览器更多的环境中

承诺队列的本机实现可以使用“微任务”队列,而不是单独的专用承诺任务队列。微队列作业仅在当前脚本线程和之前添加到微队列的任何任务完成后运行

微任务队列的细节不需要理解承诺


Promise polyfills适用于不支持promises的浏览器(所有IE版本等),在Promise响应和计时器回调的顺序上,可能会使用计时器,并且与本机实现的行为方式不完全相同。

我发现对于JS新手来说,这一点很容易理解

这是@getify的书中的复制粘贴

用一个比喻:事件循环队列就像一个游乐园游乐设施,一旦你完成了游乐设施,你就必须到队伍的后面再次乘坐。但工作队列就像完成了旅程,然后插队,然后马上回来

事件循环队列-对于承诺以外的所有异步回调,h

作业队列-用于与承诺相关的所有异步回调。1,2,3


Sync-a,b

从Es6开始,添加了作业队列运行时以适应承诺。使用
newpromise()
我们以本机方式处理异步代码
setTimeout
不是javascript的一部分,它是浏览器提供的web api的一部分

现在我们有两个队列回调队列和作业队列。作业队列也称为微任务队列

关键是,作业队列比回调队列具有更高的优先级。因此,在您的示例中,将执行第一个同步代码

 console.log('a');  // a
 console.log('b');  // b
然后将承诺发送到作业队列,并将setTimeout()发送到回调队列。现在,事件循环将首先检查作业queu,而不管setTimeout()的设置时间有多长。因为队列实现了“先进先出”,所以它们按照顺序执行,因为它们只是登录到控制台

promise.then(function(resolve) {console.log(1)}); // 1
promise.then(function(resolve) {console.log(2)}); // 2
promise.then(function(resolve) {console.log(3)}); // 3 
清除作业队列后,事件循环检查回调队列

setTimeout(function() {console.log('h')}, 0); // h

Promise是异步的-即使是像这样的内联同步代码,.then被异步调用-这就是promises dowhy在
3
之后的含义:p@JaromandaX,JS实现的作业队列很可能比浏览器实现的事件队列具有更高的优先级。但不是很确定。@JaromandaX-这和OP问的问题略有不同。我必须做一些研究,以确定这是根据规范还是根据
的方式实现的。然后()
处理程序与
setTimeout()
事件排队。@JaromandaX Promise将向作业队列添加作业,但setTimeout将在时间到期时将函数置于事件循环的末尾。当一份工作是