使用jQuery的动态AJAX承诺链
我的AJAX调用是在for循环中构建的。 它们需要按顺序(同步)。 我如何用jQuery链接它们?
var array = ['One', 'Two', 'Three']; var arrayLength = array.length; for (var arrayCounter = 0; arrayCounter < arrayLength; arrayCounter++) { var id = array[arrayCounter]; getData(id); function getData(id) { $.ajax({ url: 'http://example.com/' + id, dataType: 'jsonp', success: function(d) { var response = d; console.log(d); }, error: function() { alert("ERROR"); } }); } }
解决方案for
:
var array = ['One', 'Two', 'Three']; var id = array[0]; var data = getData(id); for (var i = 1; i < array.length; i++) { // Or only the last "i" will be used (function (i) { data = data.then(function() { return getData(array[i]); }); }(i)); } // Also, see how better the getData can be. function getData(id) { return $.ajax({ url: 'http://example.com/' + id, dataType: 'jsonp', }).done(function(d) { var response = d; console.log(d); }).fail(function() { alert('ERROR'); }); }
顺便说一句,如果你使用了正确的promises库,比如bluebird ,你将使用以下代码:
var array = ['One', 'Two', 'Three']; Promise.reduce(array, function(data, id) { return data.promise.then(function(result) { return { promise: getData(id), results: data.results.push(result) }; }); }, []).then(function(data) { console.log(data.results); // yay! }); function getData(id) { return Promise.cast($.ajax({ url: 'http://example.com/' + id, dataType: 'jsonp', }).done(function(d) { var response = d; console.log(d); }).fail(function() { alert('ERROR'); })); }
如您所见,更容易读/写。
大多数promise库都内置了jQuery吗? 不太幸运:
首先,你的函数应该返回一个promise:
function getData(id) { return $.ajax({ // note the return url: 'http://example.com/'+id, dataType: 'jsonp', success: function (d) { console.log(d); }, error: function () { alert("ERROR") } }); }
现在,使用.then
调用将它们链接在一个循环中。 请注意,只有在前一个承诺完成后才会执行.then
。 因此,他们将一个接一个地按顺序运行。
var array = ['One', 'Two', 'Three']; var p = $.when(1); // empty promise array.forEach(function(el){ p = p.then(function(){ return getData(el);; }); });
所有function将一个接一个地运行。 还剩什么? 返回值。 当前实现丢弃返回值。 我们可以将返回值放在数组中,例如:
var array = ['One', 'Two', 'Three']; var p = $.when(1); // empty promise var results = []; array.forEach(function(el,index){ p = p.then(function(){ return getData(el); }).then(function(data){ results[index] = data; // save the data }); }); p.then(function(){ // all promises done, results contains the return values });
为什么要停在那里,让它更好:)你的整个代码可以缩短为
["One","Two","Three"].map(makeUrl).map($.get).reduce(function(prev,cur,idx){ return prev.then(cur).then(function(data){ results[idx] = data; }); },$.when(1)).then(function(){ // results contains all responses here, all requests are sync }); function makeUrl(id){ return "http://example.com"+id+"?callback=?"; }