简体   繁体   中英

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.

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.

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(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.

Now, this particular code is short, but can quickly get messy as the elements and values objects get longer in length.

What method can we create to prevent the methods.updateElements method from getting too long?

While you are reading about promises, I would suggest looking at jQuery's own implementation of $.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

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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