知道所有其他准备好的回调何时完成
我想在完成所有其他处理程序后,我的处理程序就会触发ready
事件。
这对于操纵插件的不良操作非常方便。
如果我在所有其他人之后编写我的处理程序,它只能保证它会在所有其他人被解雇后触发 ,而不是完成:
$(function() { setTimeout(function() { alert('other handler'); }, 500); }); $(function() { alert('my handler'); });
小提琴
在该代码中, 我的处理程序首先发出警报
我在jQuery 1.4
版之前读到了readyList
是公开的。 所以在1.7
版本中,我不知道如何判断我的处理程序是否是最后一个处理程序。
如果想法是你不控制其他就绪处理程序,那么给出你的另一个处理程序使用setTimeout
例子,如果你的代码将在所有其他代码之后运行,你实际上永远不会知道(不检查其他代码)。
即使它是公共的, readyList
也无济于事,因为在你的例子中,具有setTimeout
的处理程序将在setTimeout
处理程序运行之前很久就从readyList
删除。 readyList
Array也没有对这种异步代码的任何控制。
所以如果你不控制(不能修改)其他代码,那么我真的没有解决方案。 但是如果其他代码只是长时间运行,而不是异步 ,那么就不会出现任何问题,因为如果你的代码是最后一个分配的.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
使用在每个就绪函数(最后一个)之外的数组,在代码片段完成时解析每个函数。
然后,在最后一个ready函数中,您只需使用$.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(); }); }
coffeescript中也是如此:
fired = 10 finished = 0 (async_function -> all_ready() if ++finished == ready) for n in [0...fired]
(我们将相同的函数调用10次以保持示例简单,而实际上您当然可以调用不同的函数,但同样的想法适用;在回调函数中,您检查计数器。)