[英]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"); } })();
如果有两个异步函数在运行并且没有什么可真正等待的:
await
,然后将被暂停。await
然后将被暂停。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.