2010-04-02 84 views
6

我已经继承了JavaScript代码,其中Ajax处理程序的成功回调启动另一个Ajax调用,其中成功回调可能会或可能不会启动另一个Ajax调用。这导致深层嵌套的匿名功能。也许有一个聪明的编程模式可以避免深层嵌套,并且更加干燥。另外,在整个函数中都会使用内部变量myVar1和myVar2。编程模式,以扁平深度嵌套ajax回调?

jQuery.extend(Application.Model.prototype, { 
    process: function() { 
     var myVar1; 
     // processing using myVar1; 
     jQuery.ajax({ 
      url:myurl1, 
      dataType:'json', 
      success:function(data) { 
       var myVar2; 
       // process data using myVar1, set state of myVar2, 
       // then send it back 
       jQuery.ajax({ 
        url:myurl2, 
        dataType:'json', 
        success:function(data) { 
         // do stuff with myVar1 and myVar2 
         if(!data.ok) { 
          jQuery.ajax({ 
           url:myurl2, 
           dataType:'json', 
           success:mycallback 
          }); 
         } 
         else { 
          mycallback(data); 
          } 

        } 
       }); 
      } 
     }); 
    } 
}); 
+1

略有关。使用服务器播放AJAX“ping-pong”是创建额外等待时间的绝对方法。您可能需要考虑是否有可能在一个请求中完成这项工作,即使这意味着要传输更多数据。 – aaaaaaaaaaaa 2010-04-02 01:15:29

回答

3

感谢链接提示和this comment,我得到了以下解决方案。我已经测试过它,它工作。可能有一些范围问题,你可以重构一个通用的ChainAjax类。但目前来看,这没关系。

jQuery.extend(MyApplication.Model.prototype, { 
    process: function() { 

     // private class for executing the Ajax calls 
     var myAjaxCalls = function(options) { 
      this.options = options; 
      this.myVar1 = null; 
      this.myVar2 =null;     
     } 
     jQuery.extend(myAjaxCalls.prototype, { 
      process1:function(data) { 
      // processsing using this.myVar1 
      this.myVar1 = 5; 
      return true; 
      }, 
      process2:function(data) { 
      this.myVar2 = 6;  
      if(data.ok) { 
       mycallback(data); 
      } 
      else { 
       return true; 
      } 
      }, 
      process3:function(data) { 
      // Process this.myVar1 and this.myVar 
      mycallback(data); 
      return false; 
      }, 
      chainAjax:function() { 
      if(this.options.length > 0) { 
       var opt = this.options.shift(); 
       var that = this; 
       jQuery.ajax({ 
       url:opt.url, 
       success:function(data) { 
        if(that[opt.callback](data)) { 
          that.chainAjax(); 
        } 
       } 
       }); 
      } 
      } 
     }); 
     // End private class 

     var calls = new myAjaxCalls([ 
      {url:'http://localhost/', callback:'process1'}, 
      {url:'http://localhost/', callback:'process2'}, 
      {url:'http://localhost/', callback:'process3'} 
     ]); 
     calls.chainAjax(); 
    } 
}); 

更新:我发现this nice presentation也与实用的编程模式和最佳实践的交易。

更新2012:在此期间有模拟与异步功能的同步流动几个库:qstratified.jsstreamline.js

9

没有必要对所有的回调是匿名和联定义,你可以在其他地方宣布他们并指定回调时,只需使用功能名称。

+0

+1击败我。 – 2010-04-02 00:49:14

1

我会建议创建一个名为“链ajax”的小工具。你给它什么你想要以什么顺序发生,然后开火。它会连锁成功,直到所有的逻辑用完。它将帮助你不再重复自己,只是代表你想要做的事情与咕噜编码的逻辑模型。

0

您可以用Frame.js这样做:

jQuery.extend(Application.Model.prototype, { 
    process: function() { 
     var myVar1; 
     // processing using myVar1; 
     Frame(function(done){ 
      jQuery.ajax({ 
       url:myurl1, 
       dataType:'json', 
       success: done 
      }); 
     }); 
     Frame(function(done, data) { 
      var myVar2; 
      // process data using myVar1, set state of myVar2, 
      // then send it back 
      jQuery.ajax({ 
       url:myurl2, 
       dataType:'json', 
       success: done 
      }); 
     }); 
     Frame(function(done, data) { 
      // do stuff with myVar1 and myVar2 
      if(!data.ok) { 
       jQuery.ajax({ 
        url:myurl2, 
        dataType:'json', 
        success:done 
       }); 
      } 
      else { 
       done(data); 
      } 
     }); 
     Frame(function(done, data){ 
      mycallback(data); 
     }); 
     Frame.start(); 
    } 
});