jQuery deferred.isRejected() 方法(长文讲解)

什么是 jQuery deferred.isRejected() 方法?

在前端开发中,异步操作是家常便饭。无论是发送 Ajax 请求、加载图片,还是处理用户交互事件,我们经常需要等待某些任务完成后再执行下一步。jQuery 为此提供了一套强大的异步处理机制,其中 deferred 对象就是核心之一。

deferred.isRejected() 方法是 jQuery 中用于判断一个 deferred 对象是否已经被拒绝(rejected)的工具。它的返回值是一个布尔值:true 表示该异步任务已经失败,false 表示尚未失败或仍在进行中。

你可以把它想象成一个“状态检查器”——就像你寄出快递后,通过物流单号查询包裹是否“已拒收”一样,isRejected() 就是帮你查看异步任务是否“失败了”。

这个方法在处理复杂流程时特别有用,比如在多个异步请求中,你希望知道是否有某个请求失败,从而决定后续流程是继续尝试、跳过还是报错。


deferred 对象的生命周期与状态

在深入 isRejected() 之前,先理解 deferred 对象的三种状态:

  • pending(待定):初始状态,异步操作尚未完成。
  • resolved(成功):异步操作成功完成。
  • rejected(拒绝):异步操作失败。

这三种状态是互斥的,一旦进入某个状态,就无法再改变。而 deferred.isRejected() 正是用于检测当前对象是否处于“rejected”状态。

💡 小贴士:deferred 不是直接创建的,而是通过 $.Deferred() 构造函数生成。它类似于 Promise 的前身,在 jQuery 1.5 中引入。

状态转换示例

// 创建一个 deferred 对象
const deferred = $.Deferred();

// 初始状态为 pending
console.log(deferred.state()); // 输出: pending

// 模拟异步操作成功
setTimeout(() => {
  deferred.resolve('任务完成');
}, 1000);

// 模拟异步操作失败
setTimeout(() => {
  deferred.reject('网络超时');
}, 500);

在上面的例子中,deferred.reject() 会将状态设为 rejected,此时调用 isRejected() 就会返回 true


如何使用 jQuery deferred.isRejected() 方法?

deferred.isRejected() 是一个无参数的方法,调用后直接返回布尔值。它不修改状态,只用于查询。

基本语法

deferred.isRejected()

返回值:

  • true:对象已被拒绝
  • false:对象未被拒绝(可能还在 pending 或已 resolved)

实际应用案例

假设你正在开发一个图片加载器,需要同时加载三张图片。如果其中任意一张失败,就显示“加载失败”提示。

// 创建三个 deferred 对象,模拟图片加载
const img1 = $.Deferred();
const img2 = $.Deferred();
const img3 = $.Deferred();

// 模拟加载过程:第一张成功,第二张失败,第三张成功
setTimeout(() => {
  img1.resolve('图片1加载成功');
}, 1000);

setTimeout(() => {
  img2.reject('图片2请求失败');
}, 800);

setTimeout(() => {
  img3.resolve('图片3加载成功');
}, 1200);

// 检查是否有一个被拒绝
function checkLoadStatus() {
  const isImg1Rejected = img1.isRejected();
  const isImg2Rejected = img2.isRejected();
  const isImg3Rejected = img3.isRejected();

  console.log('图片1是否被拒绝:', isImg1Rejected); // false
  console.log('图片2是否被拒绝:', isImg2Rejected); // true
  console.log('图片3是否被拒绝:', isImg3Rejected); // false

  // 如果任意一张被拒绝,就提示失败
  if (isImg1Rejected || isImg2Rejected || isImg3Rejected) {
    alert('部分图片加载失败,请检查网络');
  } else {
    alert('所有图片加载成功');
  }
}

// 5秒后检查状态
setTimeout(checkLoadStatus, 1500);

在这个例子中,isRejected() 帮我们精准判断了哪张图片失败,从而做出相应处理。


与其他状态检测方法对比

deferred.isRejected() 并不是孤立存在的,它与 isResolved()state() 方法共同构成了状态查询体系。

方法 作用 返回值
deferred.isResolved() 检查是否已成功 true / false
deferred.isRejected() 检查是否已被拒绝 true / false
deferred.state() 获取当前状态(pending/resolved/rejected) 字符串

三者结合使用示例

const task = $.Deferred();

// 模拟异步任务
setTimeout(() => {
  task.reject('任务失败');
}, 1000);

// 1.5秒后检查状态
setTimeout(() => {
  console.log('当前状态:', task.state()); // rejected
  console.log('是否已拒绝:', task.isRejected()); // true
  console.log('是否已成功:', task.isResolved()); // false
}, 1500);

通过组合使用这些方法,你可以构建出更智能的流程控制逻辑。比如在接口调用失败后自动重试,或跳过失败项继续执行。


实际项目中的典型应用场景

在真实项目中,deferred.isRejected() 常用于以下场景:

1. 表单提交与错误处理

当用户提交表单时,可能需要同时发送多个请求(如保存数据、上传附件、发送通知)。一旦某个请求失败,应立即提示用户。

const saveForm = $.Deferred();
const uploadFile = $.Deferred();
const sendNotification = $.Deferred();

// 模拟提交过程
setTimeout(() => {
  saveForm.resolve('数据已保存');
}, 800);

setTimeout(() => {
  uploadFile.reject('文件过大,无法上传');
}, 600);

setTimeout(() => {
  sendNotification.resolve('通知已发送');
}, 1000);

// 检查是否有失败项
function handleFormSubmission() {
  const hasError = saveForm.isRejected() || uploadFile.isRejected() || sendNotification.isRejected();

  if (hasError) {
    alert('提交失败,请检查上传文件或网络连接');
  } else {
    alert('表单提交成功');
  }
}

// 1.2秒后检查
setTimeout(handleFormSubmission, 1200);

2. 资源预加载与容错机制

在游戏或网页应用中,常需预加载资源。若某个资源加载失败,可降级为默认值。

const resources = [
  $.Deferred(), // 图片
  $.Deferred(), // 音频
  $.Deferred()  // 字体
];

// 模拟加载
setTimeout(() => resources[0].resolve('img.png'), 500);
setTimeout(() => resources[1].reject('audio.mp3 不存在'), 400);
setTimeout(() => resources[2].resolve('font.woff'), 600);

// 预加载完成后检查
setTimeout(() => {
  const failed = resources.some(r => r.isRejected());
  if (failed) {
    console.warn('部分资源加载失败,使用默认资源');
    // 可以触发 fallback 逻辑
  } else {
    console.log('所有资源加载完成');
  }
}, 700);

注意事项与常见误区

1. isRejected() 只能用于 deferred 对象

这个方法不能用于普通 Promise 或回调函数。如果你使用的是原生 Promise,应改用 Promise.catch()then() 的失败回调。

// ❌ 错误用法
const promise = new Promise((resolve) => setTimeout(resolve, 1000));
console.log(promise.isRejected()); // 报错:方法不存在

// ✅ 正确做法
promise.catch(err => {
  console.log('Promise 失败:', err);
});

2. 一旦状态确定,无法更改

deferred 的状态是单向不可逆的。一旦调用 resolve()reject(),就不能再改变。

const d = $.Deferred();
d.resolve('成功');

console.log(d.isRejected()); // false

// 再次调用 reject 不会生效
d.reject('错误'); // 不会改变状态

console.log(d.isRejected()); // 仍然是 false

3. 在链式调用中需注意时机

如果在 .then() 中使用 isRejected(),要确保异步任务已经执行完毕。

const task = $.Deferred();

task.then(() => {
  console.log('任务完成');
}).catch(() => {
  console.log('任务失败');
});

// 但此时状态尚未确定,isRejected() 仍为 false
console.log(task.isRejected()); // false

必须等待回调执行完毕后再检查。


总结

jQuery deferred.isRejected() 方法虽然看似简单,却在异步流程控制中扮演着关键角色。它让你能精准判断一个异步操作是否失败,从而实现更健壮的错误处理机制。

无论是表单提交、资源加载,还是多任务并行处理,掌握这个方法都能帮你写出更可靠的代码。它就像一个“状态探针”,在关键时刻告诉你:“这个任务,失败了。”

在实际开发中,建议结合 isResolved()state() 一起使用,构建完整的状态监控体系。虽然现代 JavaScript 已广泛使用原生 Promise,但在维护老项目或使用 jQuery 的场景下,deferred.isRejected() 依然是不可或缺的工具。

如果你正在处理复杂异步逻辑,不妨试试在关键节点加入 isRejected() 检查,你会发现程序的稳定性大幅提升。