Я наследовал код JavaScript, где обратный вызов успеха обработчика Ajax инициирует другой вызов Ajax, где обратный вызов успеха может или не может инициировать другой вызов Ajax. Это приводит к глубоко вложенным анонимным функциям. Возможно, существует умный шаблон программирования, который избегает глубокого вложения и является большим количеством DRY. Кроме того, существует проблема внутренних переменных myVar1 и myVar2, которые используются всюду по функциям.
jQuery.extend(Application.Model.prototype, {
process: function() {
var myVar1;
// processing using myVar1;
jQuery.ajax({
url:myurl1,
dataType:'json',
success:function(data) {
var myVar2;
// process data using myVar1, set state of myVar2,
// then send it back
jQuery.ajax({
url:myurl2,
dataType:'json',
success:function(data) {
// do stuff with myVar1 and myVar2
if(!data.ok) {
jQuery.ajax({
url:myurl2,
dataType:'json',
success:mycallback
});
}
else {
mycallback(data);
}
}
});
}
});
}
});
Благодаря подсказке по цепочке и этому комментарию , Я пришел к следующему решению. Я протестировал это, и он работает. Вероятно, есть некоторые проблемы с областью действия, и вы могли бы реорганизовать из него общий класс ChainAjax. Но пока это нормально.
jQuery.extend(MyApplication.Model.prototype, {
process: function() {
// private class for executing the Ajax calls
var myAjaxCalls = function(options) {
this.options = options;
this.myVar1 = null;
this.myVar2 =null;
}
jQuery.extend(myAjaxCalls.prototype, {
process1:function(data) {
// processsing using this.myVar1
this.myVar1 = 5;
return true;
},
process2:function(data) {
this.myVar2 = 6;
if(data.ok) {
mycallback(data);
}
else {
return true;
}
},
process3:function(data) {
// Process this.myVar1 and this.myVar
mycallback(data);
return false;
},
chainAjax:function() {
if(this.options.length > 0) {
var opt = this.options.shift();
var that = this;
jQuery.ajax({
url:opt.url,
success:function(data) {
if(that[opt.callback](data)) {
that.chainAjax();
}
}
});
}
}
});
// End private class
var calls = new myAjaxCalls([
{url:'http://localhost/', callback:'process1'},
{url:'http://localhost/', callback:'process2'},
{url:'http://localhost/', callback:'process3'}
]);
calls.chainAjax();
}
});
Обновление: Я нашел эту прекрасную презентацию , в которой также рассматриваются полезные шаблоны программирования и лучшие практики.
Обновление 2012 г .: Между тем существует несколько библиотек для моделирования синхронного потока с помощью асинхронных функций: q , stratified.js и streamline.js
Нет необходимости, чтобы все обратные вызовы были анонимными и определялись встроенными, вы можете объявить их в другом месте и просто использовать имя функции при указании обратного вызова.
Я бы посоветовал создать небольшой инструмент под названием «цепочка ajax». Вы даете ему то, что хотите, в каком порядке, а затем стреляете. Он будет связывать ajax в случае успеха, пока не исчерпается вся логика. Это поможет вам перестать повторяться и просто представить логическую модель того, что вы хотите сделать, и грубое кодирование.