这些代码语句以什么顺序移动到调用堆栈?
In which order these code statements are moved to call stack?
我是Javascript新手,正在尝试了解JS的执行引擎。我知道任何异步代码语句都会移动到调用堆栈,然后立即被删除并在单独的 Web API 线程(由浏览器启动)中执行。然后将结果存储在回调队列中,一旦调用堆栈为空,事件循环就会获取这些值。
谁能确认下面提到的语句移至调用堆栈的顺序?
Promise.resolve(function1)
.then(function2)
.then(function3)
.then(function4);
console.log("Hello");
整个 promise 链是移动到调用堆栈还是单个 then
s?
Does the whole promise chain move to the call stack or individual then
s ?
不是整个链条。还要注意你在这里的表达方式。各个 then
同步执行。它是异步执行的 then
的回调。我想你指的是那些回调。
链式 then
方法在不同的 promise 对象上执行,每个对象都会在 Promise Job Queue 中排队一个 reaction 处理程序,
但是 只有在 相应的 promise 解决。
所以我们这里至少有 4 个同步创建的 promise 对象。调用 Promise.resolve
创建第一个,
立即解决。所有三个 then
方法也被执行,创建了 3 个未决的承诺。
让我们将这 4 个承诺对象称为 A、B、C 和 D。因此 A 已解决,其他未决。
承诺 A 得到解决后,将在承诺作业队列中放入一个条目。我们称其为 H(A) ("Handler for reacting to resolved promise A")
这一切都是同步发生的。同步脚本最终执行完console.log
后,调用栈为空,处理Promise Job Queue:
Promise 作业队列有 H(A)。它从该队列中拉出并放入调用堆栈。
这会触发第一个 then
回调,即 function2
。
它的 return 值用于解决承诺 B。
我们应该在这里考虑 function2
return 是一个 promise E(可能是 thenable)的情况,但我们首先假设它只是 return 一个非 thenable。
使用该值解析 Promise B,并将新条目 H(B) 放入 Promise 作业队列。
调用堆栈再次为空。
再次处理 Promise 作业队列,它现在有 H(B),...因此继续。
如果 function2
、function3
和 function4
return 非 thenables,这将在一个任务中全部发生,但作业队列不会有 H(A ), H(B), H(C), H(D) 同时。
在这种情况下,队列一次只有其中一个。
更现实的情况是,像 function2
return 这样的函数是调用异步 API 的结果,例如 fetch
.
在这种情况下,承诺 B 将依赖于 function2
return 的承诺 E。此依赖项包括对 E 的 then
方法的异步调用。
无需详细介绍该过程,实质是 Promise Job Queue 可能无法立即获得条目 H(E) 。
这只会在承诺 E 解决时发生。当它发生时,调用堆栈将从作业队列中获取 H(E)。
由于依赖关系,它的执行将涉及对 H(B) 的调用。
因为这个延迟,当前的Task会在某个时刻发现Job Queue为空,任务结束。
然后事件循环将检测作业队列中何时有内容(如 H(E) )。
一些其他备注
executed in a separate Web API thread
没有单独的 Web API 线程来执行此类异步代码。所有这一切都发生在一个线程中。
也就是说,可能有 API 涉及非 JS 部分,例如访问 OS 函数,这些函数可能通过其他(非 JS)线程执行。还有
的概念
Web Workers里面得到自己的执行线程。但这与 Promises 无关。
the result is stored in a callback queue
回调队列中存储的不是异步代码执行的结果。 Promise API 在承诺解决时在队列中存储一个 Promise Reaction Record。在 Promise.resolve()
的情况下,这实际上是 同步 脚本执行的一部分。
those values are picked up by the event loop once the call stack is empty.
这里有一个精确度:有不同的队列。 Promise Job Queue 优先于其他队列,因此只要 Promise Job Queue 上有条目,例如用户 I/O 事件就不会被处理。这些条目的执行被视为同一任务的一部分。
我是Javascript新手,正在尝试了解JS的执行引擎。我知道任何异步代码语句都会移动到调用堆栈,然后立即被删除并在单独的 Web API 线程(由浏览器启动)中执行。然后将结果存储在回调队列中,一旦调用堆栈为空,事件循环就会获取这些值。
谁能确认下面提到的语句移至调用堆栈的顺序?
Promise.resolve(function1)
.then(function2)
.then(function3)
.then(function4);
console.log("Hello");
整个 promise 链是移动到调用堆栈还是单个 then
s?
Does the whole promise chain move to the call stack or individual
then
s ?
不是整个链条。还要注意你在这里的表达方式。各个 then
同步执行。它是异步执行的 then
的回调。我想你指的是那些回调。
链式 then
方法在不同的 promise 对象上执行,每个对象都会在 Promise Job Queue 中排队一个 reaction 处理程序,
但是 只有在 相应的 promise 解决。
所以我们这里至少有 4 个同步创建的 promise 对象。调用 Promise.resolve
创建第一个,
立即解决。所有三个 then
方法也被执行,创建了 3 个未决的承诺。
让我们将这 4 个承诺对象称为 A、B、C 和 D。因此 A 已解决,其他未决。
承诺 A 得到解决后,将在承诺作业队列中放入一个条目。我们称其为 H(A) ("Handler for reacting to resolved promise A")
这一切都是同步发生的。同步脚本最终执行完console.log
后,调用栈为空,处理Promise Job Queue:
Promise 作业队列有 H(A)。它从该队列中拉出并放入调用堆栈。
这会触发第一个 then
回调,即 function2
。
它的 return 值用于解决承诺 B。
我们应该在这里考虑 function2
return 是一个 promise E(可能是 thenable)的情况,但我们首先假设它只是 return 一个非 thenable。
使用该值解析 Promise B,并将新条目 H(B) 放入 Promise 作业队列。
调用堆栈再次为空。
再次处理 Promise 作业队列,它现在有 H(B),...因此继续。
如果 function2
、function3
和 function4
return 非 thenables,这将在一个任务中全部发生,但作业队列不会有 H(A ), H(B), H(C), H(D) 同时。
在这种情况下,队列一次只有其中一个。
更现实的情况是,像 function2
return 这样的函数是调用异步 API 的结果,例如 fetch
.
在这种情况下,承诺 B 将依赖于 function2
return 的承诺 E。此依赖项包括对 E 的 then
方法的异步调用。
无需详细介绍该过程,实质是 Promise Job Queue 可能无法立即获得条目 H(E) 。
这只会在承诺 E 解决时发生。当它发生时,调用堆栈将从作业队列中获取 H(E)。
由于依赖关系,它的执行将涉及对 H(B) 的调用。
因为这个延迟,当前的Task会在某个时刻发现Job Queue为空,任务结束。
然后事件循环将检测作业队列中何时有内容(如 H(E) )。
一些其他备注
executed in a separate Web API thread
没有单独的 Web API 线程来执行此类异步代码。所有这一切都发生在一个线程中。
也就是说,可能有 API 涉及非 JS 部分,例如访问 OS 函数,这些函数可能通过其他(非 JS)线程执行。还有
的概念
Web Workers里面得到自己的执行线程。但这与 Promises 无关。
the result is stored in a callback queue
回调队列中存储的不是异步代码执行的结果。 Promise API 在承诺解决时在队列中存储一个 Promise Reaction Record。在 Promise.resolve()
的情况下,这实际上是 同步 脚本执行的一部分。
those values are picked up by the event loop once the call stack is empty.
这里有一个精确度:有不同的队列。 Promise Job Queue 优先于其他队列,因此只要 Promise Job Queue 上有条目,例如用户 I/O 事件就不会被处理。这些条目的执行被视为同一任务的一部分。