jQuery deferred.done() 方法(长文解析)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在 JavaScript 的异步编程世界中,jQuery deferred.done() 方法 是一个关键工具,它帮助开发者优雅地处理异步操作的结果。无论是简单的 AJAX 请求还是复杂的异步任务链,该方法都能让代码结构更清晰、可维护性更强。本文将从基础概念入手,逐步深入讲解 jQuery deferred.done() 方法 的原理、用法及实际案例,帮助编程初学者和中级开发者掌握这一实用技能。


一、理解 Deferred 和 Promise 对象:异步编程的基石

1.1 传统回调函数的痛点

在 JavaScript 中,异步操作(如网络请求、定时器)通常通过回调函数处理结果。但随着任务复杂度增加,回调函数会形成“回调地狱”(Callback Hell),代码嵌套层级深,可读性差。例如:

function fetchData(callback) {
  setTimeout(() => {
    const data = "模拟数据";
    callback(data);
  }, 1000);
}

function processData(data) {
  console.log("处理数据:", data);
}

fetchData((result) => {
  processData(result);
  // 如果还有更多步骤,代码会不断向右缩进
});

1.2 Deferred 的引入:用对象管理异步状态

jQuery 引入了 Deferred 对象,它是一个状态容器,可以管理异步任务的生命周期。Deferred 有三种状态:

  • Pending(未完成):任务尚未完成。
  • Resolved(已成功):任务成功完成。
  • Rejected(已失败):任务因错误终止。

通过 Deferred 对象,开发者可以将异步操作封装为一个对象,方便后续处理。

1.3 Promise 的角色:接口与解耦

Promise 对象是 Deferred 的只读接口,它暴露了 done()fail()always() 等方法,允许外部代码订阅任务完成后的回调。两者的关系可以比喻为 快递员(Deferred)与快递单(Promise)

  • Deferred(快递员)负责处理包裹的运输和状态更新(如“已发货”“已签收”)。
  • Promise(快递单)是用户手中的凭证,只能查看状态或设置签收后的动作(如“收到后拆箱”)。

二、jQuery deferred.done() 方法详解

2.1 基本语法与核心功能

done() 方法用于注册一个或多个回调函数,当 Deferred 对象的状态变为 Resolved 时,这些回调会被依次执行。其基本语法为:

deferred.done(  
  function1,  
  function2,  
  ...  
);

2.2 参数传递:接收异步结果

当异步操作完成时,Deferred 对象会携带结果参数传递给 done() 的回调函数。例如:

const deferred = $.Deferred();  

deferred  
  .done((data) => {  
    console.log("成功接收数据:", data); // 输出 "成功接收数据: 成功数据"  
  });  

setTimeout(() => {  
  deferred.resolve("成功数据");  
}, 1000);  

2.3 多个回调的添加与执行顺序

开发者可以多次调用 done() 方法添加回调函数,所有回调会按添加顺序执行。例如:

deferred  
  .done(() => console.log("第一个回调"))  
  .done(() => console.log("第二个回调"));  

// 输出顺序:  
// 第一个回调  
// 第二个回调  

三、实际案例与代码示例

3.1 示例 1:简单异步任务

假设需要模拟一个 1 秒钟的异步任务(如数据加载),并用 done() 处理结果:

function asyncTask() {  
  const deferred = $.Deferred();  
  setTimeout(() => {  
    deferred.resolve("任务完成!");  
  }, 1000);  
  return deferred.promise(); // 返回 Promise 对象  
}  

asyncTask()  
  .done((result) => {  
    console.log(result); // 输出 "任务完成!"  
  });  

3.2 示例 2:AJAX 请求的处理

在真实开发中,done() 常用于处理 AJAX 请求的成功响应:

$.ajax({  
  url: "/api/data",  
  method: "GET"  
})  
.done((response) => {  
  console.log("数据获取成功:", response);  
  // 更新页面或触发下一步操作  
})  
.fail((error) => {  
  console.error("请求失败:", error);  
});  

3.3 示例 3:链式调用的高级用法

通过链式调用,可以串联多个异步操作,例如:

function step1() {  
  const deferred = $.Deferred();  
  setTimeout(() => deferred.resolve("步骤1完成"), 500);  
  return deferred.promise();  
}  

function step2() {  
  const deferred = $.Deferred();  
  setTimeout(() => deferred.resolve("步骤2完成"), 500);  
  return deferred.promise();  
}  

step1()  
  .done((result) => {  
    console.log(result); // "步骤1完成"  
    return step2(); // 返回下一个 Deferred  
  })  
  .done((nextResult) => {  
    console.log(nextResult); // "步骤2完成"  
  });  

四、错误处理与 done 方法的局限性

4.1 结合 fail 方法处理异常

done() 仅处理 Resolved 状态的结果,若异步操作失败(如网络请求错误),需通过 fail() 方法捕获:

$.ajax({  
  url: "/api/invalid-endpoint"  
})  
.done(() => console.log("成功"))  
.fail((error) => {  
  console.log("失败原因:", error.statusText); // 输出 "Not Found"  
});  

4.2 错误传递的注意事项

若在 done() 的回调中抛出错误,后续的 done() 回调不会执行,但会触发 fail() 链中的回调:

deferred  
  .done(() => {  
    throw new Error("模拟错误");  
  })  
  .done(() => console.log("不会执行"))  
  .fail((error) => {  
    console.log("捕获到错误:", error.message); // 输出 "模拟错误"  
  });  

五、进阶技巧与最佳实践

5.1 与 then 方法的对比

then() 方法可以同时处理成功和失败状态,语法为:

deferred.then(  
  (successData) => { /* 成功回调 */ },  
  (error) => { /* 失败回调 */ }  
);  

done() 仅处理成功情况,适合需要分离成功/失败逻辑的场景。

5.2 与其他 Promise 库的兼容性

jQuery 的 Deferred 对象兼容 ES6 Promise 标准,可通过 .promise() 方法与原生 Promise 交互:

const jqueryPromise = $.Deferred().resolve("数据").promise();  
Promise.resolve(jqueryPromise)  
  .then((data) => console.log(data)); // 输出 "数据"  

结论

jQuery deferred.done() 方法 是管理异步任务的利器,它通过清晰的回调注册机制,帮助开发者摆脱“回调地狱”的困扰。从基础的参数传递到复杂的链式调用,掌握这一方法能显著提升代码的可维护性和健壮性。建议读者通过实际项目练习,逐步探索 Deferred 对象与 Promise 的更多应用场景,并结合错误处理和链式调用优化异步流程的设计。

异步编程是现代 JavaScript 的核心能力之一,而 jQuery deferred.done() 方法 正是这一领域的经典工具。无论是构建单页应用、处理数据交互,还是协调复杂的异步操作,它都能为开发者提供简洁高效的解决方案。

最新发布