2

我希望我的ready事件处理程序将在所有其他处理程序完成后触发。
它对于操纵插件的不良行为非常方便。

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

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


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

小提琴

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

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

4

5 回答 5

2

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

readyList即使它是公开的也无济于事,因为在您的示例中,带有 的处理程序将在处理程序运行之前很久setTimeout就被删除。Array 也无法控制这种异步代码readyListsetTimeoutreadyList

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

于 2012-03-06T14:38:42.477 回答
0

你可以使用这样的东西:

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);
于 2012-03-06T10:50:14.660 回答
0

一个想法可能是创建一个数组deferred以在每个准备好的函数中使用(最后一个函数除外),在片段完成时解析每个函数。

然后,在最后一个准备好的函数中,您可以简单地检查承诺解决方案,$.when然后执行一些其他代码:例如

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/

于 2012-03-06T11:01:14.513 回答
0

我不知道您是否可以为所有功能创建队列,例如

var queue = [];
queue .push(fun1);
queue .push(fun2);

//execute the first function and remove it.
(queue .shift())();
于 2012-03-06T11:05:47.110 回答
0

我通常使用以下模式,简单地保持一个已完成异步函数的计数器:

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 次以保持示例简单,而实际上您当然可以调用不同的函数,但同样的想法适用;在回调函数中您检查计数器。)

于 2013-03-17T13:49:12.750 回答