Присоединяйтесь к 2 'темам' в JavaScript - PullRequest
8 голосов
/ 30 мая 2009

Если у меня есть вызов ajax с загрузкой (с обратным вызовом), а затем выполняется какой-то другой код. Как я могу иметь третью функцию, которая будет вызвана, когда оба первых 2 будут сделаны. Я уверен, что это легко с опросом (setTimeout, а затем проверить некоторые переменные), но я бы предпочел обратный вызов.

Возможно ли это?

Ответы [ 6 ]

14 голосов
/ 30 мая 2009

Вы могли бы просто дать один и тот же обратный вызов как вашему AJAX-вызову, так и вашему другому коду, выполняющемуся тем временем, использовать переменную для отслеживания их комбинированного прогресса, а затем связать их с обратным вызовом, как показано ниже:

// Each time you start a call, increment this by one
var counter = 0;

var callback = function() {
    counter--;
    if (counter == 0) {
        // Execute code you wanted to do once both threads are finished.
    }
}
4 голосов
/ 30 мая 2009

Решение Даниила правильное. Я взял его и добавил дополнительный код, чтобы вам не приходилось слишком много думать;)

function createNotifier() {
    var counter = 2;
    return function() {
        if (--counter == 0) {
            // do stuff
        }
    };
}

var notify = createNotifier();
var later = function() {
    var done = false;
    // do stuff and set done to true if you're done
    if (done) {
        notify();
    }
};

function doAjaxCall(notify) {
    var ajaxCallback = function() {
        // Respond to the AJAX callback here
        // Notify that the Ajax callback is done
        notify();
    };
    // Here you perform the AJAX call action
}

setInterval(later, 200);
doAjaxCall(notify);
3 голосов
/ 01 июня 2012

Вы говорите о вещи, называемой отложенным в javascript, как @Chris Conway, упомянутой выше. Точно так же jQuery также имеет Deferred начиная с v1.5.

Отметьте Deferred.when () или deferred.done ()

Не забудьте проверить документацию jQuery.

Но для того, чтобы дать вам некоторое представление о том, что я копирую с этого сайта.

$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1,  a2){
    /* a1 and a2 are arguments resolved for the 
        page1 and page2 ajax requests, respectively */
   var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
   if ( /Whip It/.test(jqXHR.responseText) ) {
      alert("First page has 'Whip It' somewhere.");
   }
});

// Использование deferred.then ()

$.when($.ajax("/page1.php"), $.ajax("/page2.php"))
 .then(myFunc, myFailure);
3 голосов
/ 30 мая 2009

Лучший подход к этому - использовать тот факт, что функции являются объектами первого порядка в JavaScript. Поэтому вы можете назначать их переменным и вызывать их через переменную, изменяя функцию, на которую ссылается переменная, по мере необходимости.

Например:

function firstCallback() {
    // the first thing has happened
    // so when the next thing happens, we want to do stuff
    callback = secondCallback;
}

function secondCallback() {
    // do stuff now both things have happened
}

var callback = firstCallback;

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

callback();

затем, в зависимости от того, что выполняется первым, вызывается firstCallback, который изменяет переменную так, чтобы она указывала на secondCallback, и, таким образом, будет вызываться в зависимости от того, кто выполняет вторую.

Однако ваша формулировка вопроса подразумевает, что все это может быть ненужным, так как кажется, что вы делаете запрос Ajax и затем продолжаете обработку. Поскольку интерпретаторы JavaScript являются однопоточными, обратный вызов Ajax никогда не будет выполняться до тех пор, пока основная часть кода, сделавшего запрос, не будет завершена в любом случае, даже если это происходит долго после получения ответа.

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

0 голосов
/ 30 мая 2012

Вы можете легко сделать это с помощью библиотеки закрытия Google , в частности goog.async.Deferred:

// Deferred is a container for an incomplete computation.
var ajaxFinished = goog.async.Deferred();

// ajaxCall is the asynchronous function we're calling.
ajaxCall( //args...,
    function() {  // callback
      // Process the results... 
      ajaxFinished.callback();  // Signal completion 
    }
);

// Do other stuff...

// Wait for the callback completion before proceeding
goog.async.when(ajaxFinished, function() {
    // Do the rest of the stuff...
});

Вы можете объединить несколько асинхронных вычислений, используя awaitDeferred, chainDeferred или goog.async.DeferredList.

0 голосов
/ 30 мая 2009

Примерно так (схема):

registerThread() {
  counter++;
}

unregisterThread() {
  if (--counter == 0) fireEvent('some_user_event');
}

eventHandler_for_some_user_event() {
   do_stuff();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...