JQuery 延迟对象回调挂钩的执行顺序(承诺与完成)
JQuery Execution Order of Deferred Object Callback Hooks (Promise vs. Complete)
我有一个本地托管的项目,该项目的视图向服务器发出 AJAX 请求。代码在 this jsfiddle 中重复,没有 URL 和数据参数,它们被替换为 jsfiddle 测试数据以模仿 AJAX 请求。
(function demo(iteration) {
count = iteration || 0;
if (count < 3) {
$.when(testPromise(count).promise())
.done(function () {
doSomething();
})
.always(function () {
demo(count + 1);
});
}
})();
function doSomething() {
console.log("something!");
}
function testPromise(iteration) {
var deferred = $.ajax({
type: 'POST',
url: '/echo/json/',
data: {
json: JSON.stringify({ "data": "Data!" }),
delay: 0.1
},
dataType: 'json',
beforeSend: function () {
console.log("Before Send: " + iteration);
},
success: function(response) {
console.log("Success: " + iteration);
},
error: function() {
console.log("Error: " + iteration);
},
complete: function () {
console.log("Complete: " + iteration);
}
});
return deferred;
}
现在,Jsfiddle 发出以下打印语句:
但是,我的本地代码生成了另一组打印语句:
您会注意到 jsfiddle 连续 AJAX 请求按顺序发出和完成,但本地输出显示连续请求在前一个完成之前发出:发送前: 1;完成:0 和 发送前:2;完成:1。也就是说,对于这两个环境,Promise 回调和 Complete 回调的处理顺序不同。
根据http://api.jquery.com/jquery.ajax/,
The callback hooks provided by $.ajax() are as follows:
- beforeSend callback option is invoked.
- error ...
- dataFilter ...
- success callback option is invoked, if the request succeeds.
- Promise callbacks — .done(), .fail(), .always(), and .then() — are invoked, in the order they are registered.
- complete callback option fires, when the request finishes, whether in failure or success.
除了列表顺序之外,文档并没有真正说明这些回调的顺序是否得到保证,我认为鉴于 jsfiddle 和我的本地代码不一致,顺序实际上不能保证。
那么产生这两种不同结果的背后到底发生了什么?假设我希望我的本地代码表现得像 jsfiddle(在 Promise 之前完成处理)——我可以做些什么改变来实现这个?
提前致谢-
作为旁注,我知道可以通过 AJAX .complete() 处理程序实现以下 $.when() 功能。我有意使 AJAX 函数与需要调用它的条件无关,因为我的最终目标是制作一个通用队列模块,它将处理队列处理并将给定的可延迟函数调用为必要的。因此,我无法使用 AJAX .complete() 方法。
$.when(testPromise(count).promise())
.done(function () {
doSomething();
})
.always(function () {
demo(count + 1);
});
jQuery Deferred 在版本 3.0 (https://blog.jquery.com/2016/06/09/jquery-3-0-final-released/) 中进行了更新,因此请确保您的 jQuery 版本与 fiddle (3.2.1) 上的版本相同可能有帮助。
我有一个本地托管的项目,该项目的视图向服务器发出 AJAX 请求。代码在 this jsfiddle 中重复,没有 URL 和数据参数,它们被替换为 jsfiddle 测试数据以模仿 AJAX 请求。
(function demo(iteration) {
count = iteration || 0;
if (count < 3) {
$.when(testPromise(count).promise())
.done(function () {
doSomething();
})
.always(function () {
demo(count + 1);
});
}
})();
function doSomething() {
console.log("something!");
}
function testPromise(iteration) {
var deferred = $.ajax({
type: 'POST',
url: '/echo/json/',
data: {
json: JSON.stringify({ "data": "Data!" }),
delay: 0.1
},
dataType: 'json',
beforeSend: function () {
console.log("Before Send: " + iteration);
},
success: function(response) {
console.log("Success: " + iteration);
},
error: function() {
console.log("Error: " + iteration);
},
complete: function () {
console.log("Complete: " + iteration);
}
});
return deferred;
}
现在,Jsfiddle 发出以下打印语句:
但是,我的本地代码生成了另一组打印语句:
您会注意到 jsfiddle 连续 AJAX 请求按顺序发出和完成,但本地输出显示连续请求在前一个完成之前发出:发送前: 1;完成:0 和 发送前:2;完成:1。也就是说,对于这两个环境,Promise 回调和 Complete 回调的处理顺序不同。
根据http://api.jquery.com/jquery.ajax/,
The callback hooks provided by $.ajax() are as follows:
- beforeSend callback option is invoked.
- error ...
- dataFilter ...
- success callback option is invoked, if the request succeeds.
- Promise callbacks — .done(), .fail(), .always(), and .then() — are invoked, in the order they are registered.
- complete callback option fires, when the request finishes, whether in failure or success.
除了列表顺序之外,文档并没有真正说明这些回调的顺序是否得到保证,我认为鉴于 jsfiddle 和我的本地代码不一致,顺序实际上不能保证。
那么产生这两种不同结果的背后到底发生了什么?假设我希望我的本地代码表现得像 jsfiddle(在 Promise 之前完成处理)——我可以做些什么改变来实现这个?
提前致谢-
作为旁注,我知道可以通过 AJAX .complete() 处理程序实现以下 $.when() 功能。我有意使 AJAX 函数与需要调用它的条件无关,因为我的最终目标是制作一个通用队列模块,它将处理队列处理并将给定的可延迟函数调用为必要的。因此,我无法使用 AJAX .complete() 方法。
$.when(testPromise(count).promise())
.done(function () {
doSomething();
})
.always(function () {
demo(count + 1);
});
jQuery Deferred 在版本 3.0 (https://blog.jquery.com/2016/06/09/jquery-3-0-final-released/) 中进行了更新,因此请确保您的 jQuery 版本与 fiddle (3.2.1) 上的版本相同可能有帮助。