我继承了JavaScript代码,其中Ajax处理程序的成功回调启动另一个Ajax调用,其中成功回调可能会也可能不会启动另一个Ajax调用。这导致了深层嵌套的匿名函数。也许有一个聪明的编程模式,避免深度嵌套,更干。此外,还存在整个函数中使用的内部变量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);
}
}
});
}
});
}
});
答案 0 :(得分:9)
不需要所有回调都是匿名的并且内联定义,你可以在别处声明它们,并在指定回调时使用函数名。
答案 1 :(得分:3)
感谢链接提示和this comment,我得出了以下解决方案。我测试了它,它的工作原理。可能存在一些范围问题,您可以从中重构一般的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();
}
});
更新:我发现this nice presentation还处理了有用的编程模式和最佳做法。
更新2012:与此同时,有几个库用于模拟具有异步功能的同步流:q,stratified.js和streamline.js
答案 2 :(得分:1)
我建议创建一个名为“chain ajax”的小工具。你按照什么顺序给它你想要的东西,然后开火。它将成功链接ajax直到所有逻辑耗尽。它将帮助你不再重复自己,只是代表你想要做的与grunt-coding的逻辑模型。
答案 3 :(得分:0)
您可以使用Frame.js执行此操作:
jQuery.extend(Application.Model.prototype, {
process: function() {
var myVar1;
// processing using myVar1;
Frame(function(done){
jQuery.ajax({
url:myurl1,
dataType:'json',
success: done
});
});
Frame(function(done, data) {
var myVar2;
// process data using myVar1, set state of myVar2,
// then send it back
jQuery.ajax({
url:myurl2,
dataType:'json',
success: done
});
});
Frame(function(done, data) {
// do stuff with myVar1 and myVar2
if(!data.ok) {
jQuery.ajax({
url:myurl2,
dataType:'json',
success:done
});
}
else {
done(data);
}
});
Frame(function(done, data){
mycallback(data);
});
Frame.start();
}
});