Raj*_*med 10 javascript async-await
我在想,当异步函数递归调用自己无限时会发生什么。我的想法是,它不会导致堆栈溢出。但是我无法确切指出为什么会这样。
const foo = async () => {
const txt = await Promise.resolve("foo");
console.log(txt);
foo();
}
foo();
Run Code Online (Sandbox Code Playgroud)
上面的代码无限打印“ foo”,而不会溢出堆栈。
我的想法是,代码在概念上与以下代码类似,它不会导致堆栈溢出,因为递归调用foo()位于回调内部,而对的原始调用foo()将在此之前返回。
const bar = () => {
console.log("foo");
foo();
}
const foo = () => {
setImmediate(bar);
}
foo();
Run Code Online (Sandbox Code Playgroud)
我正在寻找有关异步功能情况下的确切答案。
这个函数是语法糖
const foo = () =>
Promise.resolve(
Promise.resolve("foo")
.then(txt => {
console.log(txt);
foo();
})
);
foo();
Run Code Online (Sandbox Code Playgroud)
这本身可以用更少的依赖性重写为
const foo = () =>
queueMicrotask(() =>
queueMicrotask(() => {
console.log("foo");
foo();
})
);
foo();
Run Code Online (Sandbox Code Playgroud)
Window.queueMicrotask是一种相当新的方法,它为我们提供了一种触发队列微任务操作的方法,该操作由 Promise.resolve 触发,从而await触发。
基本上,此操作在当前执行结束时、当前事件循环结束之前推送微任务。
算法的第六点是
将任务的脚本评估环境设置对象集设置为空集。
这就是为什么这里没有堆栈溢出的原因。但是,由于您永远不会退出事件循环,因此您会阻塞浏览器。
您的代码不会产生堆栈溢出,因为当您在foo函数内部进行调用时,它不会被await编辑。如果你这样写await foo();,那么它应该会导致堆栈溢出。
考虑以下两种情况:
情况 1
这里根据您的代码。从a()它会调用foo没有await. foo()那么当它作为函数调用时会发生什么async,它也会would be scheduled to run after the current execution resolves. Or even more precisely, it will be queued for later execution立即a()从下一行继续。您可以看到首先结束的输出a(),它不等待调用堆栈foo返回;
const foo = async () => {
const txt = await Promise.resolve("foo");
console.log(txt);
}
const a = async () => {
const txt = await Promise.resolve("a");
console.log(txt);
foo();
console.log("-- ENd of a() --");
}
a();Run Code Online (Sandbox Code Playgroud)
案例 2
这里a()它会foo调用await. a()您可以看到正在等待返回的输出,foo()只有它会在下一行继续。
const foo = async () => {
const txt = await Promise.resolve("foo");
console.log(txt);
}
const a = async () => {
const txt = await Promise.resolve("a");
console.log(txt);
await foo();
console.log("-- ENd of a() --");
}
a();Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
259 次 |
| 最近记录: |