如何使用setTimeout顺序调用带不同参数的同一函数
问题
需要多次调用example函数并传入不同参数,logic函数内部使用setTimeout实现异步输出。当前两次example调用同时触发时,会交替输出数组元素,希望实现前一次example完全执行完毕后再启动下一次调用,预期输出顺序为1、2、3、4、5、6,且无需依赖固定延迟时间,能自动检测执行完成状态。
现有代码及问题输出:
let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; function logic(i, arr) { setTimeout(() => { console.log(arr[i]); }, (i + 1) * 300); } function example(arr) { for (var i = 0; i < arr.length; i++) { logic(i, arr); } } setTimeout(() => { example(arr1) }, 3000); setTimeout(() => { example(arr2) }, 3000);
现有输出:
1 4 2 5 3 6
解决方案
核心思路是通过Promise追踪异步操作的完成状态,让logic和example具备可等待的能力,从而实现串行执行。
1. 改造logic为返回Promise的异步函数
让logic返回一个Promise,在setTimeout的回调中调用resolve(),标记当前异步操作完成:
function logic(i, arr) { return new Promise(resolve => { setTimeout(() => { console.log(arr[i]); resolve(); // 通知异步操作完成 }, (i + 1) * 300); }); }
2. 改造example为异步函数,串行执行内部逻辑
使用async/await让example内部的logic按顺序执行,且整个example执行完成后返回一个Promise:
async function example(arr) { for (let i = 0; i < arr.length; i++) { await logic(i, arr); // 等待当前logic执行完毕,再启动下一个 } }
3. 按顺序调用example
通过async/await或Promise链式调用,确保前一个example执行完成后再启动下一个:
let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; // 方式1:使用async自执行函数 (async () => { await example(arr1); await example(arr2); })(); // 方式2:使用Promise链式调用 // example(arr1).then(() => example(arr2));
4. 无需setTimeout的极简方案
如果业务允许去掉logic中的setTimeout,直接同步输出,那么example就是同步函数,直接顺序调用即可:
function logic(i, arr) { console.log(arr[i]); } function example(arr) { for (let i = 0; i < arr.length; i++) { logic(i, arr); } } // 直接顺序调用 example(arr1); example(arr2);
效果说明
改造后的代码会先完整输出arr1的所有元素(1、2、3),再输出arr2的所有元素(4、5、6),完全符合预期顺序,且无需依赖固定延迟时间,由异步操作的完成状态自动触发下一次调用。
内容的提问来源于stack exchange,提问作者AloneTogether
相关产品推荐
相关产品推荐

