提问人:Won Jin Kim 提问时间:6/22/2023 最后编辑:BarmarWon Jin Kim 更新时间:6/22/2023 访问量:65
处理 JavaScript 异步函数时的执行顺序问题 (promise)
Execution order question when processing JavaScript asynchronous functions (promise)
问:
我想知道下面 JavaScript 代码的执行顺序以及原因。特别是,我想更多地了解进入微任务队列的代码内容,重点是分步
var promise = Promise.resolve();
promise = promise.then(function(rtnVal) {
console.log('1');
var promise2 = Promise.resolve();
promise2 = promise2.then(function(rtnVal) {
console.log('2');
});
promise2 = promise2.then(function(rtnVal) {
console.log('3');
});
console.log('4');
});
promise = promise.then(function(rtnVal) {
console.log('5');
var promise2 = Promise.resolve();
promise2 = promise2.then(function(rtnVal) {
console.log('6');
});
promise2 = promise2.then(function(rtnVal) {
console.log('7');
});
console.log('8');
});
console.log('9');
这是我所做的:9,1,4,2,5,8,3,6,7 ->我想知道为什么它以这个顺序运行”
答:
1赞
trincot
6/22/2023
#1
需要注意的一些事项:
- 解析 promise 后,任何回调(如果有)都将放在 PromiseJob 队列中
then
- 调用(而不是其回调)时,返回的 promise 始终处于挂起状态,即使该调用是在已解决的 promise 上进行的。这是因为返回的 promise 只能通过执行提供给方法的回调来解析,因为它决定了 promise 的解析方式,但只能异步执行。
then()
then()
then
为了便于分析,我修改了您的脚本,为每个 promise ( to ) 和每个回调函数 (, ...) 命名,但逻辑和输出保持不变:a
i
a_then
var a = Promise.resolve();
var b = a.then(function a_then() {
console.log(1);
var c = Promise.resolve();
var d = c.then(function c_then() {
console.log(2);
});
var e = d.then(function d_then() {
console.log(3);
});
console.log(4);
});
var f = b.then(function b_then() {
console.log(5);
var g = Promise.resolve();
var h = g.then(function g_then() {
console.log(6);
});
var i = h.then(function h_then() {
console.log(7);
});
console.log(8);
});
console.log(9);
下面是在执行该代码期间发生的一系列事件。
- 第一列表示正在执行的内容(主脚本、从事件循环启动的函数或从 PromiseJob 队列中取消项目排队的主机)
- 第二列包含正在计算的当前表达式/语句
- 使用该名称表示 promise 状态的列:for pending、for fulfilled。
a
i
?
F
- 最后一列描绘了由主机管理的 PromiseJob 队列中存在的内容
来吧:
任务 | 行动 | 一个 | b | c | d | e | f | g | h | 我 | PromiseJob 队列 |
---|---|---|---|---|---|---|---|---|---|---|---|
脚本 | a = Promise.resolve() |
F | - | - | - | - | - | - | - | - | |
脚本 | b = a.then(a_then) |
F | ? | - | - | - | - | - | - | - | a_then |
脚本 | f = b.then(b_then) |
F | ? | - | - | - | ? | - | - | - | a_then |
脚本 | console.log(9) |
F | ? | - | - | - | ? | - | - | - | a_then |
主机 | 出列a_then |
F | ? | - | - | - | ? | - | - | - | |
a_then |
console.log(1) |
F | ? | - | - | - | ? | - | - | - | |
a_then |
c = Promise.resolve() |
F | ? | F | - | - | ? | - | - | - | |
a_then |
d = c.then(c_then) |
F | ? | F | ? | - | ? | - | - | - | c_then |
a_then |
e = d.then(d_then) |
F | ? | F | ? | ? | ? | - | - | - | c_then |
a_then |
console.log(4) |
F | ? | F | ? | ? | ? | - | - | - | c_then |
a_then |
返回解析b |
F | F | F | ? | ? | ? | - | - | - | c_then 、b_then |
主机 | 出列c_then |
F | F | F | ? | ? | ? | - | - | - | b_then |
c_then |
console.log(2) |
F | F | F | ? | ? | ? | - | - | - | b_then |
c_then |
返回解析d |
F | F | F | F | ? | ? | - | - | - | b_then 、d_then |
主机 | 出列b_then |
F | F | F | F | ? | ? | - | - | - | d_then |
b_then |
console.log(5) |
F | F | F | F | ? | ? | - | - | - | d_then |
b_then |
g = Promise.resolve() |
F | F | F | F | ? | ? | F | - | - | d_then |
b_then |
h = g.then(g_then) |
F | F | F | F | ? | ? | F | ? | - | d_then 、g_then |
b_then |
i = h.then(h_then) |
F | F | F | F | ? | ? | F | ? | ? | d_then ,g_then |
b_then |
console.log(8) |
F | F | F | F | ? | ? | F | ? | ? | d_then ,g_then |
b_then |
返回解析f |
F | F | F | F | ? | F | F | ? | ? | d_then ,g_then |
主机 | 出列d_then |
F | F | F | F | ? | F | F | ? | ? | g_then |
d_then |
console.log(3) |
F | F | F | F | ? | F | F | ? | ? | g_then |
d_then |
返回解析e |
F | F | F | F | F | F | F | ? | ? | g_then |
主机 | 出列g_then |
F | F | F | F | F | F | F | ? | ? | |
g_then |
console.log(6) |
F | F | F | F | F | F | F | ? | ? | |
g_then |
返回解析h |
F | F | F | F | F | F | F | F | ? | h.then |
主机 | 出列h_then |
F | F | F | F | F | F | F | F | ? | |
h_then |
console.log(7) |
F | F | F | F | F | F | F | F | ? | |
h_then |
返回解析i |
F | F | F | F | F | F | F | F | F | |
主机 | 队列为空 | F | F | F | F | F | F | F | F | F |
评论
0赞
Won Jin Kim
6/23/2023
我完全印象深刻。我需要如此详细的解释,但感谢您所做的更多。我会好好分析它,让它对我的工作非常有帮助。
0赞
trincot
6/23/2023
很高兴听到它很有用!如果您愿意,也可以将答案标记为已接受,但这是可选的。
0赞
Won Jin Kim
6/23/2023
我可以再问一个问题吗?如果在“console.log(4);”下面的行中添加一个名为“return e;”的行,则9,1,4,2,5,8,3,6,7的顺序将更改为9,1,4,2,3,5,8,6,7,这是为什么?即使没有返回 promise 的语句,似乎执行了自动返回已解析 promise 的语句,那么结果不应该和第一个代码一样吗?
0赞
trincot
6/23/2023
当回调返回一个恰好是 promise 的值(如 )时,promise 链接的一个非常具体的功能就会发挥作用:在您的示例中,仍然解析,但它使用 promise 解析,这意味着它仍然处于待处理状态(未实现),并且它的命运现在与 的命运相关联(“锁定”),因此不会排队——因为只有在实现时才会发生这种情况。then
e
b
e
b_then
b
0赞
trincot
6/23/2023
参见 JS 承诺:履行与解决
评论
promise.then
只是在方便的时候安排一些事情要稍后完成。因此,所有函数都会立即返回。您连续执行 2 次调用,然后同步记录 .此时,排队的任务可以启动。then
then
9