繁体   English   中英

为什么这个循环每次重复两次?

[英]Why does this loop repeat each iteration twice?

下面的 function 将每个数字打印两次。 有人可以解释它是如何工作的吗? 我试过调试,但我能看到的是i的值只会在每两次迭代时增加。

 async function run(then) { for (let i = 1; i <= 10; i++) { console.log(i); then = await { then }; } } run(run);

具体来说,有两点我不明白。

  • 为什么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);
 .as-console-wrapper { max-height: 100%;important; }

这表明实际上启动了两个循环。 为简单起见,仅称为 A 和 B。它们记录并await ,这意味着它们的日志交错并导致 A 1、B 1、A 2、B 2 等。

发生这种情况是因为第一条语句: run(run) 它将相同的 function 作为回调传递给自身。 这不会调用回调,但这是解决这个问题的第一步。


了解正在发生的事情的下一步是await 您可以await任何值,在大多数情况下,如果它不是 promise,也没关系。 如果你有await 42; 它只是假装该值为Promise.resolve(42)并在下一个报价单立即继续操作。 大多数非承诺都是如此。 唯一的例外是thenables - 具有 .then .then()方法的对象。

当一个 thenable 被等待时,它的then()方法被调用:

 const thenable = { then() { console.log("called"); } }; (async () => { await thenable; })()

然后解释了await { then }语句。 这使用{ then: then }的简写, then是传递给run的回调。 因此它创建了一个 thenable object,当等待时,它将执行回调。

这意味着第一次run()并且在循环 A 的第一次迭代中,代码实际上是await { then: run } ,它将再次执行run ,然后启动循环 B。

then的值每次都被覆盖,因此它只并行运行两个循环,而不是更多。


还有更多与完全掌握此代码相关的功能。 我展示了一个简单的,之前只是展示等待它调用该方法。 然而,实际上await thenable将使用两个参数调用 .then .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()需要一个回调,当await { then: run }执行时它调用run(builtInResolveFunction)然后传递给下一个await { then: builtInResolveFunction }进而 resolve 导致await解析。


抛开所有这些,交错日志记录只是任务如何解决的一个因素:

 (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"); } })();

如果有两个异步函数在运行并且没有什么可真正等待的:

  1. 一个人会一直运行直到它到达await ,然后将被暂停。
  2. 另一个将运行直到它到达await然后将被暂停。
  3. 重复 1. 和 2. 直到没有等待。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM