简体   繁体   English

在Js中具有多个相关Ajax调用的循环

[英]Loop that has multiple dependent Ajax Calls in Js

This question seeks to address the mind numbing loop that contains ajax calls that are dependent on the previous ajax call. 该问题旨在解决包含依赖于先前ajax调用的ajax调用的思维麻木循环。

What would be the best and efficient way to loop through these? 遍历这些的最佳和有效方法是什么? Any terminology would be great too. 任何术语也将很棒。

Consider this example: 考虑以下示例:

elements : {
  'make' : obj,
  'model': obj,
  'trim' : obj
}
values  : {
  'model': 'a4',
  'trim' : 'base'
}

methods.updateElements(elements['make'], function(){

  methods.updateElements(elements['model'], function(){
    // Set previous element's value.
    elements['model'].val(values['model']);

    methods.updateElements(elements['trim'], function(){

      elements['trim'].val(values['trim']);  
    });
  });
});

As you can see, this previous method breaks the DRY rule of thumb. 如您所见,此先前方法打破了DRY经验法则。

Where methods.updateElements(element, callback) methods contains a simple getJson request that turns a json with an array of values into a list of options on a select element and calls the callback once completed. 其中methods.updateElements(element, callback)方法包含一个简单的getJson请求,该请求将带有值数组的json转换为select element上的选项列表,并在完成后调用callback

methods.updateElements(el, callback){
     // get the value of el
     // Get an ajax request with an array of different models
     // Append each item in the array as an option in the el
     callback();
}

As seen above, the elements['model'] depends on the previous element's value which is alone until the rest of the other relevant data is fetched. 如上所示, elements['model']依赖于前一个元素的值,直到获取其他相关数据的其余部分为止。

Now, this particular code is short, but can quickly get messy as the elements and values objects get longer in length. 现在,这个特定的代码很短,但是随着elementsvalues对象的长度变长,它很快就会变得混乱。

What method can we create to prevent the methods.updateElements method from getting too long? 我们可以创建哪种方法来防止methods.updateElements方法过长?

While you are reading about promises, I would suggest looking at jQuery's own implementation of $.Deferred . 当您阅读Promise时 ,建议您查看jQuery自己的$ .Deferred实现。

These will give you a way to keep track of concurrent asynchronous requests, or setup a chain of requests so that they will only happen once a certain set of previous requests or operations have completed. 这些将为您提供跟踪并发异步请求或设置请求链的方法,以便仅在特定的一组先前请求或操作完成后才会发生。

If you want to dig deeper into the subject you should also check out documentation on continuations: http://en.wikipedia.org/wiki/Continuation 如果您想更深入地研究该主题,则还应该查看有关延续的文档: http : //en.wikipedia.org/wiki/Continuation

May be something like this: Demo (Make sure to have the console on) 可能是这样的: 演示 (请确保打开控制台)

var
    keys = [
      'make',
      'model',
      'trim'
    ],

    elements = {
      'make' : 'makeobj',
      'model': 'modelobj',
      'trim' : 'trimobj'
    },

    values  = {
      'model': 'a4',
      'trim' : 'base'
    },

    methods = {
      updateElements : function(el, callback){
             // get the value of el
             // Get an ajax request with an array of different models
             // Append each item in the array as an option in the el
             callback();
        }
    }
;

methods.updateElements(elements['make'], function(){
  var
    func = function(keyIndex) {
        methods.updateElements(elements[keys[keyIndex]], function(){
            //elements[keys[keyIndex]].val(values[keys[keyIndex]]);
            console.log("Set " + keyIndex + ":" + elements[keys[keyIndex]] + " : " + values[keys[keyIndex]]);

            keyIndex++;

            if (keyIndex < keys.length) {
                func(keyIndex);
            }
        });
    };

    func(1);  
});

without getting into promises (a fine solution but complicated to bolt-on), you can do a lot better by simply naming your callbacks and using a dispatcher to avoid repeating code. 无需兑现承诺(一个很好的解决方案,但操作起来很复杂),您可以通过简单地命名回调并使用分派器来避免重复代码来做得更好。 This gets you out of "callback hell" and into purgatory if heaven is a promise: 如果天堂是应许,这会使您脱离“回调地狱”并进入炼狱:

elements = {
  'make' : obj,
  'model': obj,
  'trim' : obj
}
values  = {
  'model': 'a4',
  'trim' : 'base'
}


function runUpdate(kind, then){
       methods.updateElements(elements[kind], function(){then.call(methods, kind);});
}

function applyVal(n){
       elements[n].val(values[n]);  
}

function applyModel(n){
      applyVal(n);
      runUpdate('trim', applyVal);
}

function applyMake(n){
  runUpdate('model', applyModel);
}


runUpdate('make', applyMake);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM