Leo*_*nor 5 javascript for-loop repeat async-await
下面的函数将每个数字打印两次。有人可以解释它是如何工作的吗?我尝试调试,但我所看到的是 的值i仅在每第二次迭代时增加。
async function run(then) {
for (let i = 1; i <= 10; i++) {
console.log(i);
then = await { then };
}
}
run(run);Run Code Online (Sandbox Code Playgroud)
具体来说,有两点我不明白。
i每次迭代都不增加?then = await { then };做什么的?我的第一个猜测是,它会等待嵌套异步调用run完成,然后再继续下一次迭代,但情况似乎并非如此。我们可以通过小的重写来使这一点更清楚以包括日志记录:
async function run(callback) {
let then = callback;
for (let i = 1; i <= 10; i++) {
console.log(callback === run ? "A" : "B", i);
then = await { then };
}
}
run(run);Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; }Run Code Online (Sandbox Code Playgroud)
这表明实际上启动了两个循环。为简单起见,简称为 A 和 B。它们记录日志,await这意味着它们的日志交错并导致 A 1、B 1、A 2、B 2 等。
发生这种情况是因为第一个语句:run(run)。它将相同的函数作为回调传递给自身。这不会调用回调,但这是解决这个问题的第一步。
了解正在发生的事情的下一步是await。你可以设置await任何值,在大多数情况下,如果它不是承诺,那也没关系。如果你有await 42;它,就假装该值是Promise.resolve(42),并在下一个价格变动时立即继续操作。对于大多数非承诺来说都是如此。唯一的例外是thenables——有.then()方法的对象。
当等待一个 thenable 时,它的then()方法被调用:
const thenable = {
then() {
console.log("called");
}
};
(async () => {
await thenable;
})()Run Code Online (Sandbox Code Playgroud)
然后解释了该await { then }声明。这使用回调传递到{ then: then }何处的简写。因此,它创建了一个 thenable 对象,当等待时,它将执行回调。thenrun
这意味着第一次run()被执行,并且在循环 A 的第一次迭代中,代码是有效的,await { then: run }它将再次执行run,然后启动循环 B。
每次都会覆盖的值then,因此它只并行运行两个循环,而不是更多。
还有更多与完全掌握此代码相关的内容。我之前展示了一个简单的例子,它只是显示等待它调用该方法。然而,实际上await thenable将.then()使用两个参数进行调用 - 可以在成功和失败时调用的函数。与 Promise 构造函数的方式相同。
const badThenable = {
then() {
console.log("bad called");
}
};
(async () => {
await badThenable;
console.log("never reached");
})();
const goodThenable = {
then(resolve, reject) { //two callbacks
console.log("good called");
resolve(); //at least one needs to be called
}
};
(async () => {
await goodThenable;
console.log("correctly reached");
})();Run Code Online (Sandbox Code Playgroud)
这是相关的,因为run()需要一个回调,并且当await { then: run }执行时它会调用它run(builtInResolveFunction),然后将其传递给下一个await { then: builtInResolveFunction },而下一个解析又会导致 aawait解析。
撇开所有这些不谈,交错日志记录只是任务如何解决的一个因素:
(async () => {
for (let i = 1; i <= 10; i++){
console.log("A", i);
await Promise.resolve("just to force a minimal wait");
}
})();
(async () => {
for (let i = 1; i <= 10; i++) {
console.log("B", i);
await Promise.resolve("just to force a minimal wait");
}
})();Run Code Online (Sandbox Code Playgroud)
如果有两个异步函数正在运行并且没有什么可等待的:
await,然后将被暂停。await,然后将被暂停。