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

map函数内使用setTimeout时Done提前执行的问题求解

问题解决:异步任务导致"Done"提前弹出

问题原因

JavaScript中setTimeout属于异步任务,会被放入事件队列等待同步代码执行完毕后才触发。你的代码里,map会立刻遍历完数组所有元素并创建setTimeout任务,但这些任务还没执行时,同步代码alert("Done")已经先运行了,所以"Done"会比索引弹窗先出现。另外你代码里的if (index === 5)没有意义,因为arrayImages[0]只有3个元素,索引最大是2,永远不会触发这个判断。

解决方案1:用async/await按顺序执行

将clickMe改为异步函数,通过Promise包装setTimeout,配合for...of遍历实现顺序等待,最后再弹出"Done":

const arrayImages = [
    [
        { url: 'img/man.jpg' }, 
        { url: 'img/bike.jpg' }, 
        { url: 'img/sun.jpg' }
    ]
]

async function clickMe(){  
  for (const [index] of arrayImages[0].entries()) {
    await new Promise(resolve => {
      setTimeout(() => {
        alert(index);
        resolve();
      }, 2000);
    });
  }
  alert("Done");
}

解决方案2:收集Promise等待全部完成

如果想保留map的写法,可以把每个setTimeout包装成Promise,用Promise.all等待所有异步任务完成后再弹出"Done":

const arrayImages = [
    [
        { url: 'img/man.jpg' }, 
        { url: 'img/bike.jpg' }, 
        { url: 'img/sun.jpg' }
    ]
]

function clickMe(){  
  const promises = arrayImages[0].map((element, index) => {
    return new Promise(resolve => {
      setTimeout(() => {
        alert(index);
        resolve();
      }, 2000 * index);  
    });
  });

  Promise.all(promises).then(() => {
    alert("Done");
  });
}

两种方案都能保证所有索引弹窗完成后才弹出"Done",第一种是严格按顺序等待每个弹窗关闭后再执行下一个,第二种是按预设时间触发弹窗,最后等所有弹窗都处理完再显示"Done"。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:10:36