Мои вызовы AJAX построены внутри цикла for. Они должны быть в порядке (синхронно). Как связать их с jQuery?Динамическая цепочка обещаний AJAX с jQuery
ответ
Решения с использованием 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');
});
}
Кстати, если вы использовали правильное обещание библиотеку, такую как 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');
}));
}
Как вы можете видеть, путь легче читать/писать.
В большинстве библиотек с обещаниями есть встроенный с jQuery? Не так повезло:
Во-первых, ваша функция должна возвращать обещание:
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);;
});
});
Все функции будут выполняться один за другим. То, что осталось? Возвращаемое значение. Текущая реализация отбрасывает возвращаемое значение. Мы можем поставить возвращаемые значения в массиве, например:
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=?";
}
Вы действительно использовали слово «укороченное»? –
Да, я думаю, что сделал. –