I am looping through a map, where I want to make a separate AJAX call with each map value as parameter, to fetch some data and log it. See below. This is working, but I’d like to have the AJAX calls go in order of the map. Because each call is asynchronous, so seems like I should use promises to achieve execution in order. But I am new to promises and don’t really know how to do it here. I have look elsewhere on here but could not find anything. Please help.
map.forEach(function(url, key) { log(url); }); function log(url) { $.ajax({ url: url, dataType: 'json', success: function (result) { console.log(result.value); console.log(result.name); console.log(result.action); } }); }
Advertisement
Answer
Since $.ajax returns a promise, you can use promise chaining to achieve what you want
var p = $.when(); map.forEach(function(url, key) { p = p.then(function() { return log(url); }); }); function log(url) { return $.ajax({ url: url, dataType: 'json', success: function (result) { console.log(result.value); console.log(result.name); console.log(result.action); } }); }
Note: the code above uses only jQuery, no native promises
Or using reduce function of Array
map.reduce(function(p, url) { return p.then(function() { return log(url); }); }, $.when());
If you can use ES2015+, so have native Promises,
map.reduce((p, url) => p.then(() => log(url)), Promise.resolve());
If you wanted, you can also do it like this
function log(url) { return $.ajax({ url: url, dataType: 'json' }); } map.reduce((p, url) => p.then(results => log(url).then(result => results.concat(result))), Promise.resolve([])) .then(results => { results.forEach(result => { console.log(result.value); console.log(result.name); console.log(result.action); }) });
The difference being as that all the console.log’s would happen once the LAST request finished (and if any fail, none of the console log’s would happen)