如何避免回调链?

21

我需要按严格顺序调用一堆函数。同时,下一个函数等待前一个函数完成非常重要。

现在我正在使用链式回调:

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

            callMeFinal();

        });
    });
});

这个方法虽然可行,但看起来有点丑陋。

有没有其他不同的建议?


我会尽力给你一个好的答案,告诉你如何重新排列你的代码以避免这些情况,但是那个非常简单的代码示例并没有真正涉及为什么这些函数目前被链接在一起的原因... - gnarf
去年我提出过一个类似的问题,链接在这里:https://dev59.com/n3E85IYBdhLWcg3wZymt。 - Anurag
5个回答

32
如果您使用jQuery,那么可以使用queue来链接函数。
$(document)
  .queue(callMe1)
  .queue(callMe2);

其中callMeX应该是这种形式:

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

20
队列很棒...一个建议,绑定到$(document)的地方,改为绑定到$({}) -- 这样队列内部的函数可以使用this来引用同一个共享对象。 - gnarf

7
您可以实现一个“堆栈”系统:
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);
});

如果没有 jQuery 的队列,猜测这将是最好的解决方案,感激不尽。 - ezmilhouse
@Meister - 在调用方法链异步时,如何调用回调函数?因为只有push动作。 - jason

3

0

你可能想要向函数传递参数,但我认为目前还不能这样做。不过...

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);

0

使用匿名函数将您的函数及其参数包装起来,然后与.queue一起使用也可以。

在Jquery.Queue()中传递参数

var logger = function(str, callback){
    console.log(str);
    //anything can go in here, but here's 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/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接