jQuery deferred.progress() 方法(手把手讲解)

更新时间:

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

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 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+ 小伙伴加入学习 ,欢迎点击围观

前言:为什么需要进度通知?

在现代 Web 开发中,异步操作(如 AJAX 请求、文件上传、复杂计算)是常态。开发者不仅要处理操作的成功或失败,还可能需要实时追踪操作的进度,例如在文件上传时显示百分比,或在数据加载时更新界面。

jQuery 的 Deferred 对象提供了一套优雅的解决方案,而 deferred.progress() 方法正是其中用于监听异步任务进度的核心工具。它像一位“进度追踪员”,允许开发者在任务执行过程中动态获取状态信息,并据此更新用户界面或执行其他逻辑。

本文将从基础概念出发,结合代码示例,逐步讲解 deferred.progress() 的原理、用法及实际应用场景,并通过案例演示如何在真实项目中使用它。


一、Deferred 对象:异步操作的“指挥中心”

1.1 什么是 Deferred 对象?

Deferred 是 jQuery 提供的异步操作管理器,它通过三个核心方法控制任务状态:

  • done():绑定成功回调(类似 then())。
  • fail():绑定失败回调。
  • progress():绑定进度回调。

它的设计灵感来源于 Promises/A+ 规范,但更早被 jQuery 实现。可以将其想象为一个快递包裹的追踪系统

  • resolve() 表示包裹已送达(任务成功)。
  • reject() 表示包裹退回(任务失败)。
  • progress() 则是物流信息的实时更新(任务进度)。

1.2 Deferred 的生命周期

一个典型的 Deferred 对象生命周期如下:

const deferred = $.Deferred();

// 模拟异步任务(如 AJAX 请求)
setTimeout(() => {
  deferred.resolve("任务完成!"); // 触发成功回调
}, 1000);

// 绑定回调
deferred.done((result) => console.log(result)); // 输出:任务完成!

当任务需要分阶段执行时,progress() 就派上用场了。例如,上传一个大文件时,服务器可以分批次返回已上传的字节数,而 progress() 可以实时接收这些数据。


二、deferred.progress() 方法详解

2.1 方法语法与参数

deferred.progress() 的基本语法如下:

deferred.progress( progressCallback );
  • 参数
    • progressCallback:一个函数,接收进度相关的参数。这些参数由 notify() 方法触发时传递。

2.2 如何触发进度事件?

要让 progress() 监听到事件,必须在异步任务中主动调用 deferred.notify()。例如:

const deferred = $.Deferred();

// 模拟分阶段任务
setTimeout(() => {
  deferred.notify("已加载 30%"); // 触发 progress 回调
  setTimeout(() => deferred.notify("已加载 70%"), 500);
  setTimeout(() => deferred.resolve("完成!"), 1000);
}, 1000);

// 绑定进度回调
deferred.progress((progress) => {
  console.log("进度更新:", progress); // 输出两次:30% 和 70%
});

2.3 与 done/fail 的对比

方法用途触发条件
deferred.done()处理任务成功后的逻辑deferred.resolve()
deferred.fail()处理任务失败后的逻辑deferred.reject()
deferred.progress()监听任务执行中的进度deferred.notify()

关键区别

  • donefail终态回调,仅在任务结束时触发一次。
  • progress中间态回调,可多次触发,提供动态反馈。

三、实际案例:文件上传进度条

3.1 案例背景

假设需要实现一个文件上传功能,并在页面中显示实时进度条。传统方式可能需要轮询服务器或依赖原生 XMLHttpRequestupload 事件,而 Deferred 可以简化这一过程。

3.2 代码实现

步骤 1:创建 Deferred 对象并模拟上传

const deferred = $.Deferred();

// 模拟异步上传过程
function uploadFile() {
  let progress = 0;
  const interval = setInterval(() => {
    progress += 20; // 每 500ms 进度 +20%
    deferred.notify(progress); // 触发进度事件

    if (progress >= 100) {
      clearInterval(interval);
      deferred.resolve("文件上传成功!");
    }
  }, 500);
}

步骤 2:绑定进度与完成回调

deferred.progress((currentProgress) => {
  const progressBar = document.getElementById("progress-bar");
  progressBar.style.width = `${currentProgress}%`;
  progressBar.textContent = `${currentProgress}%`;
});

deferred.done(() => {
  alert("上传完成!");
});

步骤 3:HTML 结构与触发上传

<button onclick="uploadFile()">开始上传</button>
<div id="progress-bar" class="progress-container"></div>

<style>
.progress-container {
  width: 100%;
  height: 20px;
  background: #ddd;
  position: relative;
}
#progress-bar {
  background: #4CAF50;
  height: 100%;
  transition: width 0.3s;
  text-align: center;
  line-height: 20px;
  color: white;
}
</style>

3.3 运行效果

点击“开始上传”按钮后:

  1. 每 500ms 触发一次 notify(),更新进度条宽度和文本。
  2. 当进度达到 100% 时,resolve() 触发成功提示。

四、进阶技巧与常见问题

4.1 多次绑定 progress 回调

可以为同一个 Deferred 对象绑定多个 progress 回调,它们会按绑定顺序依次执行:

deferred.progress((p) => console.log("回调1:", p));
deferred.progress((p) => console.log("回调2:", p));
// 输出:  
// 回调1: 30%  
// 回调2: 30%  

4.2 在 Promise 链中使用

通过 then() 方法,可以将 progress 回调整合到 Promise 链中:

deferred.then(null, null, (progress) => {
  // 第三个参数是进度回调(需浏览器支持)
  console.log("链式进度:", progress);
});

4.3 常见问题

问题 1:进度事件未触发?

  • 确保在异步任务中调用了 deferred.notify()
  • 检查回调是否绑定在 notify() 之前。

问题 2:如何传递多个参数?

可以通过数组传递参数,回调函数接收所有参数:

deferred.notify("文件", 75, "MB/100MB"); // 传递三个参数  
deferred.progress((name, percent, detail) => {  
  console.log(`${name} ${percent}% (${detail})`);  
});

五、结论:掌握进度控制的艺术

通过 deferred.progress() 方法,开发者可以轻松实现动态反馈机制,提升用户体验。无论是文件上传、数据加载还是后台任务,这一方法都能让界面与用户保持“同频”。

关键总结

  1. Deferred 对象是管理异步任务的“总控台”,而 progress() 是它的“进度传感器”。
  2. 多次触发多回调绑定让进度控制灵活且强大。
  3. 实际案例(如上传进度条)能直观展示其价值。

建议读者在真实项目中尝试实现类似功能,并探索 Deferred 与其他 jQuery 方法(如 $.ajax())的结合使用。通过实践,您将更深入理解异步编程的优雅之处!


通过本文,我们不仅掌握了 jQuery deferred.progress() 方法 的核心用法,还通过案例与技巧,为读者提供了可直接应用的解决方案。这一方法不仅是代码优化的利器,更是提升用户感知的关键工具。

最新发布