2012-04-19 2 views
2

У меня есть следующие методы JS:Отложенный требует многократного AJAX звонки

var foo = function() { 
     var dfd = $.Deferred(); 
     console.log('foo'); 
     dfd.resolve(); 
     return dfd.promise(); 
    }; 
    var ajaxCall1 = function() { 
     var dfd = $.Deferred(); 
     $.ajax({ 
      type: 'POST', 
      contentType: 'application/json; charset=utf-8', 
      dataType: 'json', 
      url: 'xxxxxxx', 
      data: { }, 
      success: function(response) { 
       dfd.resolve(); 

      } 
     }); 
     return dfd.promise(); 
    }; 
    var ajaxCall2 = function() { 
     var dfd = $.Deferred(); 
     $.ajax({ 
      type: 'POST', 
      contentType: 'application/json; charset=utf-8', 
      dataType: 'json', 
      url: 'xxxxxxx', 
      data: {}, 
      success: function (response) { 
       dfd.resolve(); 

      } 
     }); 
     return dfd.promise(); 
    }; 
    var ajaxCall3 = function() { 
     var dfd = $.Deferred(); 
     $.ajax({ 
      type: 'POST', 
      contentType: 'application/json; charset=utf-8', 
      dataType: 'json', 
      url: 'xxxxxxx', 
      data: {}, 
      success: function (response) { 
       dfd.resolve(); 

      } 
     }); 
     return dfd.promise(); 
    }; 

и я называю их с помощью этого кода:

foo().done(function() { 
     return ajaxCall1(); 
    }).done(function() { 
     return ajaxCall2(); 
    }).done(function() { 
     return ajaxCall3(); 
    }); 

Вопрос заключается в том, что ajaxCall2 вызывается до успеха ajaxcall1 произошел. Можете ли вы помочь мне исправить это? Мне нужно сделать ajax-вызовы один за другим, когда произошел успех предыдущего.

+1

'$ .ajax()' уже возвращает отложенный объект, поэтому нет причин использовать отдельный. Вместо 'return dfd.promise()' просто верните $ .ajax ({...}) '. –

ответ

2

использовать $ .when

var deferredObject = $.ajax({}); 
$.when(deferredObject) 
.then(function(){ 
    var deferredobject2 = $.ajax({}); 
    $.when(deferredobject2) 
     .then(function(){ alert('after 2nd ajax call');}); 

    }); 
0

Упростить.

function foo() { 
    var dfd = $.Deferred(); 
    console.log('foo'); 
    dfd.resolve(); 
    return dfd.promise(); 
} 

function ajaxCall1() { 
    return $.ajax({ 
     type: 'POST', 
     dataType: 'json', 
     url: 'xxxxxxx', 
     data: { }, 
     success: function(response) { 
      console.log('ajaxCall1 success'); 
     } 
    }); 
    return dfd.promise(); 
} 

// and so on for ajaxCall2 and ajaxCall3 

Усиление.

foo().done(function() { 
    ajaxCall1().done(function() { 
     ajaxCall2().done(function() { 
      ajaxCall3(); 
     }); 
    }); 
}); 

http://jsfiddle.net/mattball/LxjDS/


Дальнейшее чтение:

+0

Невозможно написать foo(). Done (ajaxCall1()). Done (ajaxCall2()). Done (ajaxCall3()); ? Усовершенствованный метод выглядит немного громоздким. –

+0

Это передает значение _returned_ by 'ajaxCallX()' to '.done()', что означает, что вам не будет гарантирован порядок выполнения каждого вызова ajax. Если все в порядке - тогда да. Реальный пример, который я только что произвел: http://i.stack.imgur.com/C9roz.png (эта скрипка: http://jsfiddle.net/mattball/EYJfq) –

+0

Если выполнение не поддерживается, то что делать "означает? Я думал назвать несколько асинхронных вызовов, но для того, чтобы я указал –

0

То же, другой ответ, кроме упрощения обратных вызовов с Frame.js

var responses = []; 
for(var i=0; i<1000; i++){ 
    Frame(function(callback){ 
     $.ajax('myserver.api', { 
      data:i, 
      type:'post', 
      complete:function(response) { 
       responses.push(response); 
       callback(); 
      } 
     }); 
    }); 
} 
Frame.start(); 

Обычно, хлопнув браузер с помощью AJAX запросов, как это может вызвать браузер, чтобы повесить, а переменные ответа будут возвращены в порядке , а не исходный порядок, в который они были отправлены. Добавление рамки в микс здесь сортирует все это.

Или вы могли бы просто использовать его, чтобы расплющить обратные вызовы:

Frame(function(next){ 
    foo().done(next); 
}); 
Frame(function(next){ 
    ajaxCall1().done(next); 
}); 
Frame(function(next){ 
    ajaxCall2().done(next); 
}); 
Frame(function(next){ 
    ajaxCall3().done(next); 
}); 
Frame(function(next){ 
    //do more stuff 
    next(); 
}); 
Frame.start(); 
0

Прежде всего, вы можете вернуть результаты вызовов $ .ajax непосредственно, так как они не являются обещаниями уже (нет необходимости промежуточного Отложенный):

var ajaxCall1 = function() { 
    return $.ajax({ 
     type: 'POST', 
     contentType: 'application/json; charset=utf-8', 
     dataType: 'json', 
     url: 'xxxxxxx', 
     data: { } 
    }); 
}; 
var ajaxCall2 = function() { 
    return $.ajax({ 
     type: 'POST', 
     contentType: 'application/json; charset=utf-8', 
     dataType: 'json', 
     url: 'xxxxxxx', 
     data: {} 
    }); 
}; 
var ajaxCall3 = function() { 
    return $.ajax({ 
     type: 'POST', 
     contentType: 'application/json; charset=utf-8', 
     dataType: 'json', 
     url: 'xxxxxxx', 
     data: {} 
    }); 
}; 

Во-вторых, то, что вы хотите использовать это .pipe() эффективно цепь вызовов:

foo().pipe(function() { 
    return ajaxCall1(); 
}).pipe(function() { 
    return ajaxCall2(); 
}).pipe(function() { 
    return ajaxCall3(); 
}).done(function() { 
    // call1, call2 and call3 done in sequence 
}).fail(function() { 
    // one of the ajax requests failed 
}); 
0

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

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

DPAJAX at DepressedPress.com

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

// The handler function 
function AddUp(Nums) { alert(Nums[1] + Nums[2] + Nums[3]) }; 

    // Create the pool 
myPool = DP_AJAX.createPool(); 

    // Create the request 
myRequest = DP_AJAX.createRequest(AddUp); 

    // Add the calls to the request 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [5,10]); 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [4,6]); 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [7,13]); 

    // Add the request to the pool 
myPool.addRequest(myRequest); 

Заметим, что в отличие от многих других решений, при условии, что этот метод не приводит к принудительному одиночному потоку выполняемых вызовов - каждый из них будет выполняться так же быстро, как позволяет среда, но обработчик будет вызван только тогда, когда все будет завершено. Компонент также поддерживает пользовательские числа запросов, поэтому вы можете принудительно выполнить однопоточность, если хотите. Он также поддерживает настройку значений тайм-аута и попыток повтора, если ваш сервис немного ошибочен.

Я нашел это безумно полезным (и невероятно простым для понимания) для такого рода работ.