我有两个版本的异步函数
async function asyncRecurseOne(i){
try{
console.log(i)
i = i +1;
await asyncRecurseOne(i)
}catch(ex){
console.log(ex);
}
}
asyncRecurseOne(0);
这会导致最大调用堆栈大小超过 6300 左右
6246
6247
6248
RangeError: Maximum call stack size exceeded
at asyncRecurseOne (/home/amit/Projects/NodeJs/MJS/recurse.js:38:17)
at asyncRecurseOne (/home/amit/Projects/NodeJs/MJS/recurse.js:36:15)
现在在另一个版本中,我使用 sleep 方法执行以下操作
let sleep = (time) => new Promise((resolve) => setTimeout(resolve, time))
async function asyncRecurseTwo(i){
try{
console.log(i)
i = i +1;
await sleep(100);
await asyncRecurseTwo(i)
}catch(ex){
console.log(ex);
}
}
而且这个函数没有给出解决问题的最大调用堆栈大小,我在我的系统上运行直到记录了数字 20000。
第二个函数如何在不达到最大堆栈大小问题的情况下继续执行?
async
函数同步执行,直到它们到达某个点await
,此时他们返回一个承诺。您的第一段代码在此行上只有一个等待:
await asyncRecurseOne(i)
要评估这条线,需要调用asyncRecurseOne
,得到返回值,然后才可以await
。因此它将同步递归,并且下一次通过该函数将执行相同的操作,构建越来越大的调用堆栈,直到出现异常。它永远不会到达await
.
你的另一个案例没有这个问题。它到达了这一行:
await sleep(100);
睡眠创造并回报承诺。然后它击中了await
,所以你的函数返回它自己的承诺。没有增加调用堆栈。 100 毫秒后,它恢复并递归,但这个新的递归具有相同的中断,因此调用堆栈不会继续增长。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)