javascript 使用 jQuery 的延迟链接 ajax 请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8049041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chaining ajax requests with jQuery's deferred
提问by Anteru
I have a web app which must call the server multiple times. So far, I had a long nested callback chain; but I would like to use jQuery's when
,then
etc. functionality. However, I can't seem to get stuff running again after using a then
.
我有一个必须多次调用服务器的网络应用程序。到目前为止,我有一个很长的嵌套回调链;但我想用jQuery的when
,then
等功能。但是,在使用then
.
$
.when ($.get('pages/run-tool.html'))
.then (function (args)
{
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.then ($.get('pages/test.html'))
.done (function(args)
{
// This prints the same as the last call
alert (args);
});
What am I doing wrong? I guess its some scoping issue, as I can see the second get
call being executed. Using two different args
variables does not help as the argument passed to the done function is still the first get
request.
我究竟做错了什么?我想这是一些范围问题,因为我可以看到get
正在执行的第二个调用。使用两个不同的args
变量无济于事,因为传递给 done 函数的参数仍然是第一个get
请求。
回答by cdr
As an update:
作为更新:
With modern jquery (1.8+) you don't need the preliminary whenbecause getreturns a Deferred Promise.
使用现代 jquery (1.8+) 你不需要初步,因为get返回一个延迟承诺。
Also, pipeis deprecated. Use theninstead. Just be sure to return the result of the new get which becomes the Promise attached to by subsequent then/*done*/failcalls.
此外,管道已被弃用。改用then。只需确保返回新 get 的结果,该结果将成为后续then/*done*/失败调用所附加的 Promise 。
So:
所以:
$.get('pages/run-tool.html')
.then (function (args) { // this will run if the above .get succeeds
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.then (function() { // this will run after the above then-handler (assuming it ran)
return $.get('pages/test.html'); // the return value creates a new Deferred object
})
.done (function(args) { // this will run after the second .get succeeds (assuming it ran)
alert (args);
});
回答by lonesomeday
All three callbacks (the two with then
and the one with done
) are applied to the same request – the original when
call. This is because then
returns the same Deferred object, rather than a new one, so that you can add multiple event handlers.
所有三个回调(两个 withthen
和一个 with done
)都应用于同一个请求——原始when
调用。这是因为then
返回相同的 Deferred 对象,而不是新对象,因此您可以添加多个事件处理程序。
You need to use pipe
instead.
你需要pipe
改用。
$
.when ($.get('pages/run-tool.html'))
.then (function (args)
{
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.pipe (function() {
return $.get('pages/test.html'); // the return value creates a new Deferred object
})
.done (function(args)
{
alert (args);
});
回答by MarzSocks
Here is an wonderfully simple and highly effective AJAX chaining / queue plugin. It will execute you ajax methods in sequence one after each other.
这是一个非常简单且高效的 AJAX 链接/队列插件。它将一个接一个地依次执行 ajax 方法。
It works by accepting an array of methods and then executing them in sequence. It wont execute the next method whilst waiting for a response.
它的工作原理是接受一组方法,然后按顺序执行它们。它不会在等待响应时执行下一个方法。
//--- THIS PART IS YOUR CODE -----------------------
$(document).ready(function () {
var AjaxQ = []; AjaxQ[0] = function () { AjaxMethod1(); } AjaxQ[1] = function () { AjaxMethod2(); } AjaxQ[3] = function () { AjaxMethod3(); } //Execute methods in sequence $(document).sc_ExecuteAjaxQ({ fx: AjaxQ });
});
//--- THIS PART IS THE AJAX PLUGIN -------------------
$.fn.sc_ExecuteAjaxQ = function (options) {
//? Executes a series of AJAX methods in dequence var options = $.extend({ fx: [] //function1 () { }, function2 () { }, function3 () { } }, options); if (options.fx.length > 0) { var i = 0; $(this).unbind('ajaxComplete'); $(this).ajaxComplete(function () { i++; if (i < options.fx.length && (typeof options.fx[i] == "function")) { options.fx[i](); } else { $(this).unbind('ajaxComplete'); } }); //Execute first item in queue if (typeof options.fx[i] == "function") { options.fx[i](); } else { $(this).unbind('ajaxComplete'); } }
}
//--- 这部分是你的代码 ---------------
$(document).ready(function () {
var AjaxQ = []; AjaxQ[0] = function () { AjaxMethod1(); } AjaxQ[1] = function () { AjaxMethod2(); } AjaxQ[3] = function () { AjaxMethod3(); } //Execute methods in sequence $(document).sc_ExecuteAjaxQ({ fx: AjaxQ });
});
//--- 这部分是 AJAX 插件 -------------------
$.fn.sc_ExecuteAjaxQ = 函数(选项){
//? Executes a series of AJAX methods in dequence var options = $.extend({ fx: [] //function1 () { }, function2 () { }, function3 () { } }, options); if (options.fx.length > 0) { var i = 0; $(this).unbind('ajaxComplete'); $(this).ajaxComplete(function () { i++; if (i < options.fx.length && (typeof options.fx[i] == "function")) { options.fx[i](); } else { $(this).unbind('ajaxComplete'); } }); //Execute first item in queue if (typeof options.fx[i] == "function") { options.fx[i](); } else { $(this).unbind('ajaxComplete'); } }
}
回答by cl yu
The answer cdr gave, which has the highest vote at the moment, is not right.
目前票数最高的cdr给出的答案是不正确的。
When you have functions a, b, c each returns a $.Deferred() object, and chains the functions like the following:
当你有函数 a、b、c 时,每个函数都返回一个 $.Deferred() 对象,并像下面这样链接函数:
a().then(b).then(c)
Both b and c will run once the promise returned from a is resolved. Since both then() functions are tied to the promise of a, this works similiar to other Jquery chaining such as:
一旦从 a 返回的承诺得到解决, b 和 c 都会运行。由于 then() 函数都与 a 的承诺相关联,因此其工作方式类似于其他 Jquery 链接,例如:
$('#id').html("<div>hello</div>").css({display:"block"})
where both html() and css() function are called on the object returned from $('#id');
在 $('#id') 返回的对象上调用 html() 和 css() 函数;
So to make a, b, c run after the promise returned from the previous function is resolved, you need to do this:
所以要让a,b,c在前一个函数返回的promise被解析后运行,你需要这样做:
a().then(function(){
b().then(c)
});
Here the call of function c is tied to the promise returned from function b.
这里函数 c 的调用与函数 b 返回的承诺相关联。
You can test this using the following code:
您可以使用以下代码对此进行测试:
function a() {
var promise = $.Deferred();
setTimeout(function() {
promise.resolve();
console.log("a");
}, 1000);
return promise;
}
function b() {
console.log("running b");
var promise = $.Deferred();
setTimeout(function () {
promise.resolve();
console.log("b");
}, 500);
return promise;
}
function c() {
console.log("running c");
var promise = $.Deferred();
setTimeout(function () {
promise.resolve();
console.log("c");
}, 1500);
return promise;
}
a().then(b).then(c);
a().then(function(){
b().then(c)
});
Change the promise in function b() from resolve() to reject() and you will see the difference.
将函数 b() 中的 promise 从 resolve() 更改为 reject() ,您将看到不同之处。
回答by Du?an Stanojevi?
<script type="text/javascript">
var promise1 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("1");
def.resolve();
}, 3000);
}).promise();
};
var promise2 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("2");
def.resolve();
}, 2000);
}).promise();
};
var promise3 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("3");
def.resolve();
}, 1000);
}).promise();
};
var firstCall = function () {
console.log("firstCall");
$.when(promise1())
.then(function () { secondCall(); });
};
var secondCall = function () {
console.log("secondCall")
$.when(promise2()).then(function () { thirdCall(); });
};
var thirdCall = function () {
console.log("thirdCall")
$.when(promise3()).then(function () { console.log("done"); });
};
$(document).ready(function () {
firstCall();
});
</script>
回答by iamwhitebox
I thought I would leave this little exercise here for anyone who may find it useful, we build an array of requests and when they are completed, we can fire a callback function:
我想我会把这个小练习留在这里给任何可能觉得有用的人,我们构建一个请求数组,当它们完成时,我们可以触发一个回调函数:
var urls = [{
url: 'url1',
data: 'foo'
}, {
url: 'url2',
data: 'foo'
}, {
url: 'url3',
data: 'foo'
}, {
url: 'url4',
data: 'foo'
}];
var requests = [];
var callback = function (result) {
console.log('done!');
};
var ajaxFunction = function () {
for (var request, i = -1; request = urls[++i];) {
requests.push($.ajax({
url: request.url,
success: function (response) {
console.log('success', response);
}
}));
}
};
// using $.when.apply() we can execute a function when all the requests
// in the array have completed
$.when.apply(new ajaxFunction(), requests).done(function (result) {
callback(result)
});
回答by kungtu
My way is to apply callback function:
我的方法是应用回调函数:
A(function(){
B(function(){
C()})});
where A, B can be written as
其中 A, B 可以写成
function A(callback)
$.ajax{
...
success: function(result){
...
if (callback) callback();
}
}