Зная, когда все другие готовые обратные вызовы сделаны - PullRequest
2 голосов
/ 06 марта 2012

Я хочу, чтобы мой обработчик события ready сработал после того, как все остальные обработчики сделали .
Это очень удобно для манипулирования нежелательными действиями плагинов.

Если я напишу свой обработчик после всех остальных, он только гарантирует, что он будет запускаться после всех остальных запущен , не завершен:

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


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

Fiddle

В этом коде мой обработчик предупредил первым.

Я читал, что до версии jQuery 1.4 readyList был общедоступным.поэтому в версии 1.7 я понятия не имею, как определить, что мой обработчик - последний обработчик или нет.

Ответы [ 5 ]

2 голосов
/ 06 марта 2012

Если идея заключается в том, что вы не управляете другими готовыми обработчиками, то, учитывая ваш пример, где другой обработчик использовал setTimeout, вы никогда не узнаете (без проверки другого кода), будет ли ваш код работать после всех другой код.

readyList не помогло бы, даже если бы оно было общедоступным, потому что в вашем примере обработчик с setTimeout будет удален из readyList задолго до запуска обработчика setTimeout. Массив readyList также не имеет никакого контроля над асинхронным кодом такого рода * 1009.

Так что, если вы не контролируете (не можете изменить) другой код, тогда у меня действительно нет решения. Но если другой код просто долго выполняется, но не асинхронный , тогда проблем не будет, потому что, если ваш код является последним назначенным обработчиком .ready(), не должно иметь значения, как долго другие обработчики берутся выполнить. Если их код синхронный , он заставит вас ждать, пока они не будут завершены. Просто если они используют асинхронный код, как, например, ваш setTimeout пример, то вы ничего не можете сделать, кроме изучения другого кода и изменения своего кода, чтобы он работал последним.

0 голосов
/ 17 марта 2013

Я обычно использую следующий шаблон, просто сохраняя счетчик законченных асинхронных функций:

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 раз для простоты примера, хотя в действительности вы, конечно, можете вызывать разные функции, но применима одна и та же идея; в функции обратного вызова вы проверяете счетчик.)

0 голосов
/ 06 марта 2012

Идея может заключаться в создании массива 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/

0 голосов
/ 06 марта 2012

Я не знаю, возможно ли для вас создать очередь для всех функций, таких как

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

//execute the first function and remove it.
(queue .shift())();
0 голосов
/ 06 марта 2012

Вы можете использовать что-то вроде этого:

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