当子函数包含不同的延迟时,嵌套的setTimeout函数

时间:2017-06-15 15:22:01

标签: javascript jquery

我有一组大约100个参数,这些参数都需要不同的时间来运行给定的函数。每个都是页面上的简短动画,根据参数动画不同的部分,每个动画大约需要1-3秒。

我查了一下:Nested setTimeout alternative?

...但它仅在子功能花费相同的时间时才有效,

我可以按顺序收集数组中的参数,即:

args = [arg1,arg2,arg3,arg4 ...]

目前我的电话如下:

 setTimeout(myfunction(arg1), 3000);
 setTimeout(myfunction(arg2), 5000);
 setTimeout(myfunction(arg3), 7500);
 setTimeout(myfunction(arg4), 8500);...

我真的希望能够有代码说“当myfunction(arg1)完成时,等待500毫秒然后执行myfunction(arg2),然后当完成时等待500毫秒并执行func3等。 “

我不知道如何将其纳入setTimeouts的运行或myfunction()的定义。

谢谢。

3 个答案:

答案 0 :(得分:1)

您可以在上一个setTimeout的回调中安排下一个任务,如下所示:

var tasks = [
    { arg : "arg1", delay : 3000},
    { arg : "arg2", delay: 2000},
    { arg : "arg3", delay : 2500}
];

function myFunction(arg) {
    console.log(new Date(),arg);
}

function schedule() { 
    var task = tasks.shift();
    if(task) {
        setTimeout(function() {
            myFunction(task.arg);               
            if(tasks.length) schedule();
        },task.delay);
    }
}

schedule();

此代码将在3000毫秒内调用myFunction("arg1"),然后在+ 2000毫秒内调用myFunction("arg2"),然后在+ 2500毫秒调用myFunction("arg3")

每次删除(移动)“任务列表”的第一个元素时, 然后一旦它是空的就停止。

请注意,此代码将改变您的tasks数组(通过在每次迭代时从中移除下一个任务),因此您将无法重复使用它。

如果这是一个问题,只需使用显式索引来解决下一个任务:

function schedule(tasks,i) {
    if(i<tasks.length) {
        setTimeout(function() {
            myFunction(tasks[i].arg);               
            if(i+1<tasks.length) schedule(tasks,i+1);
        },tasks[i].delay);
    }
}

schedule(tasks,0);

答案 1 :(得分:1)

Promises是链接异步操作的完美方式。 如果您可以考虑更改myFunction的正文以便它返回promise,那么您可以轻松地链接这些操作。

myFunction的正文看起来像这样

function myFunction(args, time) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      // here you do your stuff
      resolve(); // resolve the promise when it's done
    }, time);
  })
}

你这么称呼它

var args = [
  { args: "", timeout: 100 },
  { args: "", timeout: 300 }
]

var promise = Promise.resolve();

args.forEach(function (animation) {
  promise = promise
    .then(myFunction.bind(null, animation.args, animation.timeout))
    // ^ chaining promise so that they fire one after another
})

答案 2 :(得分:0)

我认为解决这个问题的最简单方法是承诺链:

var args = [1, 2, 3, 4, 5, 6]
var i = 0;

function doStuff(arg) {
  //do stuff
  console.log(arg)
}

function getPromise(cb, arg, time){
  return function() {
    return new Promise(function(resolve){
      setTimeout(function(){
        cb(arg)
        resolve()
      }, time)
    })
  }
}

var promise_chain = Promise.resolve();
while (args[i]) {
  promise_chain  = promise_chain.then(getPromise(doStuff, args[i++], 500))
}

此代码将生成一堆承诺。每个人等待500ms来解决自己并执行下一堆代码。希望这有帮助。