Как избежать вложенных функций при использовании AJAX? - PullRequest
5 голосов
/ 12 мая 2010

Последовательные асинхронные вызовы брутто.Есть ли более удобочитаемое решение?

Проблема в том, что за этим трудно следовать:

ajaxOne(function() {
  // do something
  ajaxTwo(function() {
    // do something
    ajaxThree()
  });
});

, где анонимные функции - это обратные вызовы, которые вызываются при ответе сервера.

Я использую сторонний API для выполнения вызовов AJAX, поэтому мне нужно универсальное решение.

Ответы [ 4 ]

3 голосов
/ 12 мая 2010

функциональное программирование на помощь! jsdeferred позволяет написать ваш пример так:

next(ajaxOne).next(ajaxTwo).next(ajaxThree).error(function(e){alert('An error happened:' + e)})

каждая из «последовательных» функций ajaxOne / Two / Three получает возвращенный результат своего предшественника в качестве параметра. Если вам нужно передать дополнительные параметры, вы можете представить их в глобальном объекте, прежде чем вызывать свою цепочку AJAX.

1 голос
/ 16 января 2013

Во-первых, я должен признать, что я относительно новичок в JavaScript, но недавно я столкнулся с той же проблемой при использовании функции jQuery ajax. Мне пришлось загрузить пару документов через POST на сервер в определенном порядке. Вложив все обратные вызовы, вы получите полностью испорченный код. Я подумал о решении после прочтения ответов и нашел решение, которое отлично сработало. Он использует только одну функцию с предложением switch для различения различных вызовов обратного вызова:

var callback = function(sCallIdentifier, callbackParameters){
  switch(sCallIdentifier){
     case "ajaxOne":
        doYourStuff(callbackParameters); //do your stuff for ajaxOne
        ajaxTwo(function(newCallbackParameters){
           /*define a anonymous function as actual method-callback and pass the call-identifier, together with all parameters, to your defined callback function*/
           callback("ajaxTwo", newCallbackParameters);
        });
       break;
     case "ajaxTwo":
       doYourStuff(callbackParameters);
       ajaxThree(function(newCallbackParameters){
          callback("ajaxThree", newCallbackParameters);
       });
       break;
     case "ajaxThree":
       doYourStuff();
       break;
 }
});

Если это не очень хорошая идея, пожалуйста, дайте мне знать. Как я уже сказал, я не эксперт по JavaScript, но у меня это получилось неплохо.

Лучший, Рене

* * 1008 Edit: * * 1010

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

1 голос
/ 12 мая 2010

Если у вас есть только одна вложенная функция, то можно оставить все как есть, но если у вас есть несколько вложенных вызовов, вам следует рассмотреть возможность написания этих обратных вызовов в отдельном методе и вызова из вложенной функции ...

ajaxOne(function(result) { handleAjaxOneCallback(result, someExtraNeededArg); } );

function handleAjaxOneCallback(result, someExtraNeededParam) {
  // do something

  ajaxTwo(function(result) { handleAjaxTwoCallback(result, myFoo, myBar); });
}

function handleAjaxTwoCallback(result, foo, bar) {
  // do something

  ajaxThree(/* ... */);
}
0 голосов
/ 12 мая 2010

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

var ajaxOne = function() {
    doTheAjax(callbackOne);
}
var callbackOne = function() {
    //funny things ...
    doTheAjax(callbackTwo);
}
var callbackTwo = function() {
    //even more funny things ...
}
...