最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - JavaScript Function Queue - Stack Overflow

programmeradmin5浏览0评论

I have a ton of functions that need to run in succession, but not before the other has pleted. What I need is a way to queue these functions to run only after the previous function was successfully pleted. Any Ideas?

Function1();
Function2();
Function3();
Function4();
Function5();

I have a ton of functions that need to run in succession, but not before the other has pleted. What I need is a way to queue these functions to run only after the previous function was successfully pleted. Any Ideas?

Function1();
Function2();
Function3();
Function4();
Function5();
Share Improve this question edited Oct 2, 2022 at 19:34 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Feb 10, 2011 at 2:26 user610728user610728 2452 gold badges4 silver badges6 bronze badges 5
  • Your code should work just fine ... (if by "sucessfully pleted" you mean that the function returned) – Šime Vidas Commented Feb 10, 2011 at 2:30
  • 1 Is there async stuff in your functions? If not, I can't see a problem. – spender Commented Feb 10, 2011 at 2:31
  • Most of my functions contain AJAX calls. And each one depends on a success from the previous call. – user610728 Commented Feb 10, 2011 at 2:32
  • 1 You may look in to playing with deferring calls (as of jQuery 1.5). They probably have a way of writing plugins that bind to the success/failure events so it drops right in to jQuery's environment. – Brad Christie Commented Feb 10, 2011 at 2:51
  • Nice ment on jQuery deferreds. I've use them in Twisted before but didn't know they were in the new jQuery. – jpsimons Commented Feb 10, 2011 at 3:32
Add a ment  | 

6 Answers 6

Reset to default 8

You could use something like this:

var FunctionQueue = (function(){
    var queue = [];
    var add = function(fnc){
        queue.push(fnc);
    };
    var goNext = function(){
        var fnc = queue.shift();
        fnc();
    };
    return {
        add:add,
        goNext:goNext
    };
}());

and use it like this:

var fnc1 = function(){
    window.setTimeout(function(){
        alert("1 done");
        FunctionQueue.goNext();
    }, 1000);
};

var fnc2 = function(){
    window.setTimeout(function(){
        alert("2 done");
        FunctionQueue.goNext();
    }, 5000);
};

var fnc3 = function(){
    window.setTimeout(function(){
        alert("3 done");
        FunctionQueue.goNext();
    }, 2000);
};

FunctionQueue.add(fnc1);
FunctionQueue.add(fnc2);
FunctionQueue.add(fnc3);
FunctionQueue.goNext();

Edit after a few years: Another way people are approaching this is to pass in a next function that you can call to continue the chain. Like so:

var Queue = function(arr){
    var index = 0;
    var next = function(){
        if (index >= arr.length) {return;}
        arr[index++](next);
    };
    return next;
};

var fn1 = function(next){
    console.log("I am FN1");
    next();
};

var fn2 = function(next){
    console.log("I am FN2");
    setTimeout(next,1000);
};

var fn3 = function(next){
    console.log("I am FN3");
    setTimeout(next,3000);
};

var fn4 = function(next){
    console.log("I am FN4");
    setTimeout(next,1000);
};

Queue([fn1, fn2, fn3, fn4])();

You could create a Queue function:

function Queue(arr) {
    var i = 0;
    this.callNext = function() { 
        typeof arr[i] == 'function' && arr[i++]();
    };
}

So if these were your functions...

function f1() {
    alert(1);   
}

function f2() {
    alert(2);   
}

function f3() {
    alert(3);   
}

... you just pass them (their references) inside a new Queue instance:

var queue = new Queue([f1, f2, f3]);

Then you execute callNext() to call the functions sequentially:

queue.callNext();
queue.callNext();
queue.callNext();

Live demo: http://jsfiddle/CEdPS/3/

Why don't you do exactly as you have shown, by listing them in a covering function?

function do_1_to_5() {
    Function1(); 
    Function2(); 
    Function3(); 
    Function4(); 
    Function5();
}

If your function contains AJAX calls, then you need to hook them up at the end of the callback functions that handle the AJAX calls.

To make sure they run consecutively, you might return a value from each one and use that returned value in the subsequent one...

function do_1_to_5() {

    r1 = Function1(); 
    r2 = Function2(r1); 
    r3 = Function3(r2); 
    r4 = Function4(r3); 
    r5 = Function5(r4);

}

You don't need all that machinery, just put your functions in an array. Then you can loop over them.

var runThese = [
    Function1,
    Function2, 
    Function3,
    Function4,
    Function5
];

JavaScript is single-threaded so you're guaranteed one finishes before the next starts.

for (var i = 0; i < runThese.length; i++) {
    runThese[i]();
}

Or since your functions have deterministic names, you could avoid the array altogether:

for (var i = 1; i <= 5; i++) {
    window["Function" + String(i)]();
}

Check out async.js - it provides a mechanism for chaining up functions so they execute asynchronously or one after another, with an excellent way to catch the results and/or errors from all the executed functions.

https://github./caolan/async

发布评论

评论列表(0)

  1. 暂无评论