javascript - 在不同的函数调用语法中,承诺的控制流如何在 javascript 中导航
问题描述
我有doSomething
, doSomethingElse
&finalHandler
功能如下:
function doSomething() {
console.log('doSomething(): start');
return new Promise(function (resolve) {
setTimeout(function () {
console.log('doSomething(): end');
resolve();
}, 1000);
});
}
function doSomethingElse() {
console.log('doSomethingElse(): start');
return new Promise(function (resolve) {
setTimeout(function () {
console.log('doSomethingElse(): end');
resolve();
}, 1000);
});
}
function finalHandler() {
console.log('finalHandler(): start');
return new Promise(function (resolve) {
setTimeout(function () {
console.log('finalHandler(): end');
resolve();
}, 1000);
});
}
我有一个example1
看起来像这样的函数:
function example1() {
doSomething().then(function () {
return doSomethingElse();
}).then(finalHandler);
}
正在返回
doSomething(): start
doSomething(): end
doSomethingElse(): start
doSomethingElse(): end
finalHandler(): start
finalHandler(): end
我有example2
:
function example2() {
doSomething().then(function () {
doSomethingElse();
}).then(finalHandler);
}
返回:
doSomething(): start
doSomething(): end
doSomethingElse(): start
finalHandler(): start
doSomethingElse(): end
finalHandler(): end
并且example3
:
function example3() {
doSomething().then(doSomethingElse())
.then(finalHandler);
}
返回:
doSomething(): start
doSomethingElse(): start
doSomething(): end
finalHandler(): start
doSomethingElse(): end
finalHandler(): end
并且example4
:
function example4() {
doSomething().then(doSomethingElse)
.then(finalHandler);
}
返回:
doSomething(): start
doSomething(): end
doSomethingElse(): start
doSomethingElse(): end
finalHandler(): start
finalHandler(): end
我可以理解不同的函数调用语法会给出不同的结果——但是这种行为背后的概念是什么?
我不是在寻找更正或优化的代码。我想知道如何使用不同的语法导航流程?
解决方案
这里的概念 -
- 任务是微任务队列将在一个执行上下文结束时耗尽,然后从宏任务队列中挑选任务。
- 已解决的承诺回调是一个微任务。
- setTimeout 的回调是一个宏任务。
- 被链接的 then 只会等待 previous then,如果 previous then 会返回一个 Promise。如果它是除了承诺之外的任何东西,那么下一个 then 将不会等待上一个 then。
- 传递对函数的引用与调用函数不同。例如1
doSomething() 进入调用堆栈 -> doSomething(): start print 它返回一个承诺,该承诺将在 1 秒后解决,然后将调用“then”处理程序。由于没有解决的承诺或任务,程序返回。如果您在 chrome 中执行,您可以使用未定义的打印来验证。1 秒后,第一个 Promise 被解决,在 doSomething 中排队。如语句 console.log(' doSomething(): end '); 是同步的,它会被打印出来。
.then(function () {
return doSomethingElse();
})
现在执行。与上面相同的流程 - console.log('doSomethingElse(): start'); --> 1 秒后 doSomethingElse end 与最后一个 then 相同:console.log('finalHandler(): start'); --> 1 秒后 console.log('finalHandler(): end');
示例 2 与示例 1的不同之处在于,在第一个示例中,doSomethingElse 返回了一个承诺。之后的 then 链接将等待在执行之前解决该承诺。但在示例 2 中,即使 doSomethingElse 返回一个承诺,我们也不会在 then 处理程序回调中返回它,这就是为什么将执行 doSomethingElse 和 setTimeout 的事件将为 doSomethingElse(): end 设置,then for final 处理程序将立即执行,因为它不会等待前一个承诺被解决。只有在之前重新调整了一个承诺时,它才会等待。因此finalHandler(): start首先打印。之后,doSomethingElse 超时和 finalHandler 超时的计时器都会到期,但之前的超时将在任务队列中排在第一位,因此它会首先被打印。
关于不同的格式.. 当您执行.then(doSomethingElse)时,您传递的是对该函数的引用,因此与您在 then.then() 中复制 doSomethingElse 的完整代码相同。它是一个有效的回调。但是当你执行.then(doSomethingElse())时,它只是执行函数 doSomethingElse,但它不是回调,所以没有得到任何回调,它只是未定义,因此链中的下一个 then 被执行。
剩下的两个例子现在应该是不言自明的了。
推荐阅读
- javascript - JQuery 自动完成 - 无法动态设置源
- c# - 用于返回 maxId 的 C# 泛型方法
- oracle - Spark - Oracle 时区错误
- reporting-services - SSRS 比较两个不同文本框中的值行。
- unreal-engine4 - 为什么在使用“for循环”和“选择节点”时“从类中生成演员”不执行多次
- java - Java中是否有strpbrk等价物?以及如何使用它?
- kubernetes - 节点与互联网完全隔离
- ibm-cloud - 提供 $timezone 上下文变量不会改变 Watson Assistant 中的 now() 行为
- uitableview - 在 UITableView 中加载数据时,活动指示器出现问题
- mysql - 从 3 个不同的表创建一个视图