Как накапливать данные от различных вызовов AJAX? - PullRequest
5 голосов
/ 07 июня 2011

Помимо выполнения синхронных вызовов AJAX, если вы можете и считаете это уместным, каков наилучший способ обработки чего-либо подобного?

var A = getDataFromServerWithAJAXCall(whatever);
var B = getDataFromServerWithAJAXCallThatDependsOnPreviousData(A);
var C = getMoreDataFromServerWithAJAXCall(whatever2);

processAllDataAndShowResult(A,B,C);

При условии, что я могу передать обратные вызовы этим функциям, я знаю, что могу использовать замыкания и лямбда-выражения для выполнения работы следующим образом:

var A,B,C;

getDataFromServerWithAJAXCall(whatever, function(AJAXResult) {
    A= AJAXResult;
    getDataFromServerWithAJAXCallThatDependsOnPreviousData(A, function(AJAXResult2) {
        B= AJAXResult2;
        processAllDataAndShowResult(A,B,C);
    });
});
getMoreDataFromServerWithAJAXCall(whatever2, function(AJAXResult) {
    C= AJAXResult;
    processAllDataAndShowResult(A,B,C);
});

function processAllDataAndShowResult(A,B,C) {
    if(A && B && C) {
        //Do stuff
    }
}

Но мне это не кажется правильным или достаточно чистым. Так есть ли лучший способ или хотя бы более чистый способ сделать то же самое или просто я не привык к функциональному программированию на javascript?

Кстати, я использую jQuery (1.4.2), если это поможет.

Спасибо.

Ответы [ 4 ]

5 голосов
/ 07 июня 2011

Да, jQuery Отложенный объект очень удобен.

Вот пример из $.when() функции документации , иллюстрирующий решение вашей проблемы:

$.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.");
   }
});

Ура!

0 голосов
/ 29 ноября 2012

Используйте так называемую «защелку обратного отсчета»

  1. Каждая из функций имеет свой собственный обратный вызов.
  2. Пропускать переменную с именем countdownlatch каждый раз, когда вызывается функция, и выполнять обратный отсчет при достижении каждого из обратных вызовов (обязательно также обратный отсчет при асинхронной ошибке.
  3. Каждыйиз колбэков отдельно проверяет, если countdownlatch==0 если это так, вызывайте функцию processAllDataAndShowResult

Прелесть javascript в такого рода асинхронной синхронизации заключается в том, что реализация обратного отсчета очень проста, потому что javascriptоднопотоковый, то есть: countdownlatch не может получить причудливые числа из-за гоночных условий, поскольку они отсутствуют (в этой ситуации).

РЕДАКТИРОВАТЬ

Не видел, чтобы B зависел от A, но применяется тот же принцип:

var A,B,C;
var cdlatch = 2;
getDataFromServerWithAJAXCall(whatever, function(AJAXResult) {
    A= AJAXResult;
    getDataFromServerWithAJAXCallThatDependsOnPreviousData(A, function(AJAXResult2) {
        B= AJAXResult2;
        if(--cdlatch === 0){
          processAllDataAndShowResult(A,B,C);
        }
    });
});
getMoreDataFromServerWithAJAXCall(whatever2, function(AJAXResult) {
    C= AJAXResult;
    if(--cdlatch === 0){
      processAllDataAndShowResult(A,B,C);
    }  
});

function processAllDataAndShowResult(A,B,C) {
   //Do stuff
}

Я должен признать, что это не так ясно, как общий случай, который я описал ранее, да ладно.

0 голосов
/ 07 июня 2011

Сделайте функцию обратного вызова каждого вызова AJAX для проверки / сохранения результатов в общем локальном хранилище .И есть другая функция обработки, которая читает из этого контейнера, возможно, через равные промежутки времени или активируется каждым обратным вызовом.Таким образом вы сохраняете свои функции в чистоте и сосредотачиваетесь на вызове Ajax.Это также позволяет легко наращивать накопление до n вызовов Ajax, и вам не нужно изменять существующий код при добавлении нового вызова.

0 голосов
/ 07 июня 2011

Если вы можете использовать jQuery 1.5, вы сможете выполнить свои потребности с помощью отложенного объекта и $.when()

$.when(getDataFromServerWithAJAXCall("Call 1"), getMoreDataFromServerWithAJAXCall("Call 2")).done(function(a1, a2) {
    var jqXHR = a1[2];
    jqXHR.responseText;
    getDataFromServerWithAJAXCallThatDependsOnPreviousData(jqXHR.responseText);
});

Просто укажите, когдапервые две функции завершены, затем будет выполнена третья функция.

Пример jsfiddle

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