jQuery从1.5版本开始引入了类似Promise的接口来处理异步操作,称为Deferred对象。它提供了一种更优雅的方式来处理异步操作,特别是AJAX请求。
jQuery主要提供两种相关对象:
$.Deferred()
:创建可手动控制的Promise对象$.ajax()
返回的Promise:自动管理的AJAX请求Promisefunction asyncOperation() {
var deferred = $.Deferred();
setTimeout(function() {
// 模拟异步操作成功
deferred.resolve("操作成功完成");
// 或者失败
// deferred.reject("操作失败");
}, 1000);
return deferred.promise();
}
asyncOperation()
.done(function(result) {
console.log("成功:", result);
})
.fail(function(error) {
console.log("失败:", error);
});
$.ajax({
url: "api/data",
method: "GET"
})
.then(function(data) {
console.log("获取数据成功:", data);
return $.ajax({
url: "api/process",
method: "POST",
data: {input: data}
});
})
.then(function(processedData) {
console.log("处理数据成功:", processedData);
})
.fail(function(error) {
console.error("操作失败:", error);
});
原因:在then()链中抛出异常但没有对应的错误处理
解决:
// 添加fail处理
promiseChain
.then(step1)
.then(step2)
.fail(function(error) {
console.error("链中出错:", error);
});
解决方案:使用$.when()
$.when(
$.ajax("/api/data1"),
$.ajax("/api/data2")
).then(function(result1, result2) {
console.log("两个请求都完成了", result1, result2);
});
解决方案:使用Promise链替代嵌套回调
// 不好的做法
$.ajax({
url: "api/first",
success: function(data1) {
$.ajax({
url: "api/second",
data: {id: data1.id},
success: function(data2) {
// 更多嵌套...
}
});
}
});
// 好的做法
$.ajax("api/first")
.then(function(data1) {
return $.ajax({
url: "api/second",
data: {id: data1.id}
});
})
.then(function(data2) {
// 处理data2
});
function longOperation() {
var deferred = $.Deferred();
var progress = 0;
var interval = setInterval(function() {
progress += 10;
deferred.notify(progress);
if (progress >= 100) {
clearInterval(interval);
deferred.resolve("完成");
}
}, 300);
return deferred.promise();
}
longOperation()
.progress(function(percent) {
console.log("进度:", percent + "%");
})
.done(function(result) {
console.log(result);
});
function withTimeout(promise, timeout) {
var deferred = $.Deferred();
var timer = setTimeout(function() {
deferred.reject("操作超时");
}, timeout);
promise
.then(function(result) {
clearTimeout(timer);
deferred.resolve(result);
})
.fail(function(error) {
clearTimeout(timer);
deferred.reject(error);
});
return deferred.promise();
}
// 使用
withTimeout($.ajax("api/data"), 5000)
.then(function(data) {
console.log("数据:", data);
})
.fail(function(error) {
console.error("错误:", error);
});
jQuery的Promise实现虽然不是完全符合Promises/A+标准,但在大多数场景下提供了类似的便利性,特别是在处理AJAX请求和动画序列时非常实用。
没有搜到相关的文章