代码之家  ›  专栏  ›  技术社区  ›  chiborg Alessandro Minoccheri

扁平深度嵌套的Ajax回调的编程模式?

  •  6
  • chiborg Alessandro Minoccheri  · 技术社区  · 14 年前

    我继承了javascript代码,其中Ajax处理程序的成功回调会启动另一个Ajax调用,成功回调可能会或可能不会启动另一个Ajax调用。这导致了深度嵌套的匿名函数。也许有一个聪明的编程模式,可以避免深嵌套,而且更干燥。此外,还有内部变量myvar1和myvar2的问题,这些变量在整个函数中使用。

    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);
                                }
    
                        }
                    });
                }
            });
        }
    });
    
    4 回复  |  直到 11 年前
        1
  •  9
  •   cpalmer    14 年前

    不需要所有回调都是匿名的并且是内联定义的,您可以在其他地方声明它们,并且在指定回调时只使用函数名。

        2
  •  3
  •   Community CDub    7 年前

    多亏了链接提示和 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年更新: 同时,有几个库用于模拟具有异步函数的同步流: q , stratified.js streamline.js

        3
  •  1
  •   Dmitriy Likhten    14 年前

    我建议创建一个叫做“chain-ajax”的小工具。你把你想发生的事情按顺序给它,然后开火。它将成功地链接Ajax,直到所有的逻辑都用完。它将帮助您停止重复您自己,并且只代表您想要完成的与咕噜编码的逻辑模型。

        4
  •  0
  •   BishopZ    11 年前

    你可以这样做 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();
        }
    });