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.