当您有需要按顺序完成的事情列表时,使异步函数本身调用是个好主意吗?

例:

async continueWork(){

   if(!this.list.length)
     return;

   var next = this.list.shift();

   // do things with next

   await this.continueWork();
}


如果列表很大,会发生什么?会引起问题吗?

最佳答案

是的,这可能会引起问题。每个continueWork调用都放在最后一个continueWork顶部的调用堆栈中,这可能导致溢出:



let i = 0;
async function continueWork() {
  i++;
  if (i < 1e5) {
    await continueWork();
  }
}

continueWork()
  .then(() => console.log('ok'))
  .catch((err) => {
    console.log('err');
    console.log(err.stack);
  });





您可以通过awaitcontinueWork内部进行递归调用之前对其进行修复,以使调用堆栈不会堆积:



let i = 0;
async function continueWork() {
  i++;
  await Promise.resolve();
  if (i < 1e5) {
    await continueWork();
  }
}

continueWork()
  .then(() => console.log('ok'))
  .catch((err) => {
    console.log('err');
    console.log(err.stack);
  });





重要的是要确保在调用堆栈清空之前没有大量同步函数调用。 await(或.then)确保await.then回调之后的内容在微任务中执行(仅在清除调用堆栈后才会发生)。

10-07 18:03