使用AJAX时如何避免嵌套函数?

时间:2010-05-12 12:36:24

标签: javascript ajax readability

顺序异步调用很严重。有更可读的解决方案吗?

问题是这很难理解:

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

其中匿名函数是在服务器响应上调用的回调。

我正在使用第三方API进行AJAX调用,因此我需要一个通用解决方案。

4 个答案:

答案 0 :(得分:3)

功能性编程救援! jsdeferred让你像这样编写你的例子:

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

每个“顺序”ajaxOne / Two / Three函数接收其前身的返回结果作为参数。如果需要传入其他参数,可以在调用ajax链之前在全局对象中公开它们。

答案 1 :(得分:1)

如果你只有一个嵌套函数,可以保持原样,但是如果你有几个嵌套调用,你应该考虑在一个单独的方法中编写这些回调,并从嵌套函数调用它......

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(/* ... */);
}

答案 2 :(得分:1)

首先我必须承认,我对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专家,但我对我的工作非常好。

最佳, 勒

修改

过了一会儿,我发现Promises是解决这个问题的更好办法。

答案 3 :(得分:0)

如果您不需要回调中的闭包范围(您可能不会),则可以将回调放入单独的函数中并按名称调用它们。像:

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