Как избежать цепочек обратного вызова?

Мне нужна куча функций, которые вызывают в строгом порядке. Также очень важно, чтобы следующая функция ожидала, пока предыдущий не завершится.

Прямо сейчас я использую цепные обратные вызовы:

callMe1(function(){
    callMe2(function(){
        callMe3(function(){

            callMeFinal();

        });
    });
});

Это работает, но кажется немного уродливым.

Любые предложения для другого подхода?

Ответ 1

Если вы используете jQuery, вы можете использовать queue, чтобы связать функции.

$(document)
  .queue(callMe1)
  .queue(callMe2);

где callMeX должен иметь вид:

function callMeX(next) {
    // do stuff
    next();
}

Ответ 2

Вы можете реализовать систему "стек":

var calls = [];

function executeNext(next) {
    if(calls.length == 0) return;
    var fnc = calls.pop();
    fnc();
    if(next) {
        executeNext(true);
    }
}

/*To call method chain synchronously*/
calls.push(callMe3);
calls.push(callMe2);
calls.push(callMe1);
executeNext(true);

/*To call method chain asynchronously*/
calls.push(callMe3);
calls.push(function(){
    callMe2();
    executeNext(false);
});
calls.push(function(){
    callMe1();
    executeNext(false);
});

Ответ 3

Не уверен, что это вам поможет, но есть хорошая статья о с использованием отложенных в jQuery 1.5. Это может немного очистить вашу цепочку...

Кроме того, мой ответ на Может ли кто-нибудь объяснить мне очередь jQuery для меня, есть некоторые примеры использования очереди для обеспечения последовательных вызовов.

Ответ 4

Возможно, вы захотите передать параметры функциям, я не верю, что вы можете на момент написания этой статьи. Однако...

function callMe1(next) {
    console.log(this.x);
    console.log("arguments=");
    console.log(arguments);
    console.log("/funct 1");
    this.x++;
    next();
}
function callMe2(next) {
    console.log(this.x);
    console.log("arguments=");
    console.log(arguments);
    console.log("/funct 2");
    this.x++;
    next();
}
function callMe3(next) {
    console.log(this.x);
    console.log("arguments=");
    console.log(arguments);
    console.log("/funct 3");
    this.x++;
    next();
}
var someObject = ({x:1});
$(someObject).queue(callMe1).queue(callMe2).queue(callMe3);

Ответ 5

Работает с вашими функциями, неповрежденными аргументами, с анонимной функцией, которая играет вместе с .queue.

Передача аргументов в JQuery.Queue()

var logger = function(str, callback){
    console.log(str);
    //anything can go in here, but here a timer to demonstrate async
    window.setTimeout(callback,1000)
}

$(document)
.queue(function(next){logger("Hi",next);})
.queue(function(next){logger("there,",next);})
.queue(function(next){logger("home",next);})
.queue(function(next){logger("planet!",next);});

Пример в JSFiddle: http://jsfiddle.net/rS4y4/