You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让async函数等待所有异步操作?解决函数提前返回问题

问题分析与解决方案

你的问题核心出在两个地方:一是**setAsyncTimeout没有正确等待异步回调完成**,二是混合使用await和.then()导致嵌套逻辑混乱,部分异步操作没被纳入等待链。这就导致putToDeath的Promise提前resolve,所以done会在setAsyncTimeout 463之前输出。

第一步:修复setAsyncTimeout函数

原来的setAsyncTimeout在执行回调后立刻resolve了Promise,但如果回调是async函数(里面有await),它并不会等待回调内部的异步操作完成。我们需要修改它,确保等待回调的异步逻辑执行完毕:

const setAsyncTimeout = (cb, timeout = 0) => 
  new Promise(resolve => setTimeout(async () => {
    await cb(); // 等待异步回调中的所有操作完成
    resolve();
  }, timeout));

第二步:重构putToDeath,移除.then()嵌套

混合await和.then()很容易造成逻辑层级混乱,我们把所有.then()替换成await,让代码线性化,确保每一步都等待前一个异步操作完成:

async function putToDeath(conNum, exeNum) { 
  let exeStartX = round(players[exeNum].x);
  let exeStartY = round(players[exeNum].y);

  console.log('walkTo 452');
  await walkTo(conNum, window.innerWidth / 2, window.innerHeight / 2, 0.5);
  
  faceAudience(conNum, 'walk');
  console.log('setAsyncTimeout 455');
  await setAsyncTimeout(async () => { 
    let exe = players[exeNum];
    let direction = pointDirection(exe.x, exe.y, window.innerWidth / 2, window.innerHeight / 2);
    let distance = lineLength(exe.x, exe.y, window.innerWidth / 2, window.innerHeight / 2);
    let dest = getLineEndpoint(exe.x, exe.y, direction, distance - 50);

    console.log('walkTo 461');
    await walkTo(exeNum, dest.x, dest.y, 0.75);
    
    console.log('setAsyncTimeout 463');
    await setAsyncTimeout(async () => { 
      swingSword(exeNum);
      await setAsyncTimeout(async () => { 
        await die(conNum);
        await setAsyncTimeout(async () => { 
          face(exeNum, 'walk', false);
          await setAsyncTimeout(async () => { 
            await walkTo(exeNum, exeStartX, exeStartY, 0.75);
            face(exeNum, 'walk', true); // 如果这个方法是异步的,记得加上await
          }, 500);
        }, 500);
      }, 750);
    }, 500);
  }, 1000);
}

为什么这样修改能解决问题?

  1. 修复后的setAsyncTimeout:现在它会等待回调内部的所有异步操作完成后才resolve,确保每一个超时后的逻辑都执行完毕再进入下一步。
  2. 线性化的await逻辑:移除.then()嵌套后,每一个await都会等待前一个异步操作完成,整个函数的Promise会一直等到最内层的face(exeNum, 'walk', true)执行完毕才会resolve。

这样当你执行putToDeath(0, 1).then(()=>{ console.log('done') })时,done会在所有操作(包括setAsyncTimeout 463之后的逻辑)完成后才输出。

内容的提问来源于stack exchange,提问作者Meler Lawler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:41:23