Nested setTimeout alternative?

前端 未结 6 1574
逝去的感伤
逝去的感伤 2020-12-10 04:22

I need to execute 3 functions in a 1 sec delay.

for simplicity those functions are :

console.log(\'1\');
console.log(\'2\');
console.log(\'3\');


        
相关标签:
6条回答
  • 2020-12-10 04:37

    You can use something like this with setTimeout:

    var funcs = [func1, func2, func3],
        i = 0;
    
    function callFuncs() {
        funcs[i++]();
        if (i < funcs.length) setTimeout(callFuncs, 1000);
    }
    setTimeout(callFuncs, 1000); //delay start 1 sec.
    

    or start by just calling callFuncs() directly.

    Update

    An setInterval approach (be aware of the risk of call stacking):

    var funcs = [func1, func2, func3],
        i = 0,
        timer = setInterval(callFuncs, 1000);
    
    function callFuncs() {
        funcs[i++]();
        if (i === funcs.length) clearInterval(timer);
    }
    
    0 讨论(0)
  • 2020-12-10 04:40

    There are here two methods. One with setTimeout and anotherone with setInterval. The first one is better in my opinion.

    for(var i = 1; i++; i<=3) {
      setTimeout(function() {
          console.log(i);
        }, 1000*i);
    }
    // second choice:
    var i = 0;
    var nt = setInterval(function() {
          if(i == 0) return i++;
          console.log(i++);
          if(i>=3) clearInterval(nt);
        }, 1000);

    0 讨论(0)
  • 2020-12-10 04:45

    Assuming you run it on a modern browser or have added support for array.map this is quite concise:

    [func1, func2, func3].map(function (fun, index) {
        setTimeout(fun, 1000 + index * 1000);
    }
    
    0 讨论(0)
  • 2020-12-10 04:45

    There is a new type of function declaration called generators in es6 (a.k.a ecmascript 6, es2015). It is incredibly useful for this situation, and makes your async code look synchronous. es6 is the latest standard of JavaScript as of 2015. It works on modern browsers but you can use Babel and its javascript polyfill to use generators now even on older browsers.

    Here is a tutorial on generators.

    The function myDelayedMessages below is an example of a generator. Run is a helper function that takes a generator function which it calls and provides a function to advance the generator as the first argument of the generator function that it called.

    function delay(time, callback) {
          setTimeout(function () {
            callback();
          }, time);
    }
    
    function run(generatorFunction) {
      var generatorItr = generatorFunction(resume);
      function resume(callbackValue) {
        generatorItr.next(callbackValue);
      }
      generatorItr.next()
    }
    
    run(function* myDelayedMessages(resume) {
      for(var i = 1; i <= 3; ++i) {
        yield delay(1000, resume);
        console.log(i);
      }
    });

    This is an overview of the code which is similar to the above tutorial's final overview.

    1. run takes our generator and creates a resume function. run creates a generator-iterator object (the thing you call next on), providing resume.
    2. Then it advances the generator-iterator one step to kick everything off.
    3. Our generator encounters the first yield statement and calls delay.
    4. Then the generator pauses.
    5. delay completes 1000ms later and calls resume.
    6. resume tells our generator to advance a single step.
    7. Our generator continues from the spot it yielded at then console.logs i, which is 1, then continues the loop
    8. Our generator encounters the second call to yield, calls delay and pauses again.
    9. delay waits 1000ms and ultimately calls the resume callback. resume advances the generator again.
    10. Our generator continues from the spot it yielded at then console.logs i, which is 2, then continues the loop.
    11. delay waits 1000ms and ultimately calls the resume callback. resume advances the generator again.
    12. Our generator continues from the spot it yielded at then console.logs i, which is 3, then continues and the loop finishes.
    13. There are no more calls to yield, the generator finishes executing.
    0 讨论(0)
  • 2020-12-10 04:47
    setTimeout(function(){console.log('1')}, 1000);
    setTimeout(function(){console.log('2')}, 2000);
    setTimeout(function(){console.log('3')}, 3000);
    
    0 讨论(0)
  • 2020-12-10 04:58

    I think most simple way to do this is to create some closures within a function.
    First i'll recall that you have big interest in using setInterval, since the overhead of the setTimeout might have it trigger 10ms off target. So especially if using short (<50ms) interval, prefer setInterval. So we need to store the function array, the index of latest executed function, and an interval reference to stop the calls.

    function chainLaunch(funcArray, time_ms) {
      if (!funcArray || !funcArray.length) return;
      var fi = 0; // function index
      var callFunction = function () {
          funcArray[fi++]();
          if (fi==funcArray.length)
                  clearInterval(chainInterval);
       } ;
      var chainInterval = setInterval( callFunction, time_ms);
    }
    

    Rq : You might want to copy the function array ( funcArray = funcArray.slice(0); )
    Rq2 : You might want to loop within the array
    Rq3 : you might want to accept additionnal arguments to chainlaunch. retrieve them with var funcArgs = arguments.slice(3); and use apply on the functions : funcArray[fi++].apply(this,funcArgs);

    Anyway the following test works :

    var f1 = function() { console.log('1'); };
    var f2 = function() { console.log('2'); };
    var f3 = function() { console.log('3'); };
    
    var fArr = [f1, f2, f3];
    
    chainLaunch(fArr, 1000);
    

    as you can see in this fiddle : http://jsfiddle.net/F9UJv/1/ (open the console)

    0 讨论(0)
提交回复
热议问题