知道所有其他准备好的回调何时完成



我希望我的ready事件处理程序在所有其他处理程序都完成后启动
它非常方便地处理插件不需要的操作。

如果我在所有其他人之后编写我的处理程序,它只保证它会在所有其他被解雇之后被解雇,而不是完成:

$(function() {
    setTimeout(function() { alert('other handler'); }, 500);
});

$(function() { alert('my handler'); });​

Fiddle

在该代码中,我的处理程序首先发出警报。

我读到在jQuery版本1.4之前,readyList是公开的。所以在版本1.7中,我不知道如何判断我的处理程序是否是最后一个处理程序。

如果你的想法是不控制其他准备好的处理程序,那么在你的例子中,另一个处理程序使用了setTimeout,你永远无法真正知道(如果不检查其他代码)你的代码是否会在所有其他代码之后运行。

readyList即使是公共的也没有帮助,因为在您的示例中,早在setTimeout处理程序运行之前,带有setTimeout的处理程序就会从readyList中删除。readyList阵列也不能控制这种异步代码。

所以,如果你不能控制(不能修改)其他代码,那么我真的没有解决方案。但是,如果其他代码只是长时间运行,而不是异步,那么就不会有任何问题,因为如果您的代码是最后分配的.ready()处理程序,那么其他处理程序执行所需的时间应该无关紧要。如果他们的代码是同步的,它将迫使你的代码等待,直到它们完成。只是,如果他们使用异步代码,就像您的setTimeout示例一样,那么除了检查其他代码并修改您的代码以确保它最后启动之外,您别无选择。

您可以使用这样的东西:

function Join(cb) {
    var paths = 0;
    var triggerCallback = cb;
    this.add = function () {
        paths ++;
        return this.call;
    };
    this.call = function () {
        paths --;
        if (paths == 0)
            if (triggerCallback)
                triggerCallback();
    };
    return this;
}

一个例子:

function finishedAll() {
    alert("All finished");
}
window.join = new Join(finishedAll);
function sampleCall(callJoinHandle) {
    alert("Not done yet.");
    if (callJoinHandle) callJoinHandle();
}
var cb1 = join.add();
setTimeout(function () { sampleCall(cb1); }, 1000);
var cb2 = join.add();
setTimeout(function () { sampleCall(cb2); }, 1000);
var cb3 = join.add();
setTimeout(function () { sampleCall(cb3); }, 1000);

一个想法可以是创建一个deferred数组,用于每个就绪函数(除了最后一个),并在代码段完成时解析每个函数。

然后,在最后一个就绪函数中,您可以简单地用$.when检查promise解析,然后执行一些其他代码:例如

var dfdArray = [];
$(function() {
    var dfd = $.Deferred();
    dfdArray.push(dfd);
    setTimeout(function() { 
      console.log('another simple handler'); 
      dfd.resolve(); 
    }, 2000);
});

$(function() {
    var dfd = $.Deferred();
    dfdArray.push(dfd);
    setTimeout(function() { 
        console.log('first handler'); 
        dfd.resolve(); 
    }, 1200);
});

$(function() {
    $.when.apply($, dfdArray).done(function() {
      alert('my final handler');
    })
});

请点击此处查看小提琴演奏:http://jsfiddle.net/DXaw5/

我不知道是否可以为等所有函数创建一个队列

var queue = [];
queue .push(fun1);
queue .push(fun2);
//execute the first function and remove it.
(queue .shift())();

我通常使用以下模式,只需保持已完成异步函数的计数器:

var fired = 10;
var finished = 0;
for (var i = 0; i < fired; i++) {    
    // Call an asynchronous function 10 times
    async_function(function() {
        // When asynchronous function finishes,
        // we check if it was the last one.
        if (++finished == fired) all_ready();
    });
}

咖啡脚本中也是如此:

fired = 10
finished = 0
(async_function -> all_ready() if ++finished == ready) for n in [0...fired]

(为了简化示例,我们调用同一个函数10次,而实际上您当然可以调用不同的函数,但同样的想法适用;在回调函数中,您可以检查计数器。)

最新更新