前端开发中如何取消Promise操作

前端开发中如何取消Promise操作

前言

在 JavaScript 中,Promise 本身没有内置的取消机制,但我们可以通过一些模式来实现类似取消的功能。以下是几种常见的实现方式

方法一:使用 Promise.race() 模拟取消

Promise.race 静态方法接受一个 promise 可迭代对象作为输入,并返回一个 Promise。这个返回的 promise 会随着第一个 promise 的敲定而敲定。 那么我们可以传给它两个Promise,一个正常执行,一个我们将Promise的reject方法缓存下来,只需要在我们需要取消的时候调用即可

javascript 复制代码
// 封装取消函数
const cancelPromise = (promise) => {
  let cancel
  // 定义一个取消的Promise
  const rejectPromise = new Promise((_, reject) => {
    cancel = () => {
      reject({ name: 'cancel' })
    }
  })
  const resultPromise = Promise.race([promise, rejectPromise])
  return {
    cancel,
    promise: resultPromise
  }
}
const { cancel, promise } = cancelPromise(
  new Promise((resolve) => {
    // 3s之后完成
    setTimeout(() => {
      resolve({ data: [] })
    }, 3000)
  })
)
promise
  .then((res) => {
    console.log('Promise Resolve', res)
  })
  .catch((error) => {
    // 'cancel'
    console.log(error.name)
  })
setTimeout(() => {
  cancel()
}, 2000)

方法二:使用 AbortController(推荐)

AbortController 是一个构造函数,其signal我们可以传给fetch Api,然后我们只需要调用abort方法就可以取消该请求axios也支持该方法取消。

javascript 复制代码
const controller = new AbortController()
fetch('http://api.com/query', { signal: controller.signal })
  .then((res) => {
    console.log(res)
  })
  .catch((error) => {
    if (error.name === 'AbortError') {
      console.log('Promise 已取消')
    }
  })
// 超时取消
setTimeout(() => {
  controller.abort()
}, 2000)

被取消的请求会被浏览器标记为canceled

方法三:使用 Bluebird 库

Bluebird 是一个完善的Promise库,其完全遵循Promises/A+标准,所以我们可以像日常使用Promise一样使用他,而且它有许多超越原生Promise的功能、比如支持 Promise 取消、进度追踪、超时控制、更强大的错误处理机制(如 OperationalError)等。我们使用时候只需要安装后直接引入即可

csharp 复制代码
yarn add bluebird
javascript 复制代码
import Promise from 'bluebird'
...
// 打开取消功能
Promise.config({ cancellation: true })
const testPromise  = new Promise((resolve, reject, onCancel) => {
  setTimeout(() => {
    resolve('成功')
  }, 3000)
  onCancel(function () {
    console.log('promise 已被取消')
  })
})
  .then((res) => {
    console.log(res)
  }).finally(() => {
    // 判断Promise是否取消
    if(testPromise.isCancelled()) {
      console.log('promise 已被取消')
    }
  })
setTimeout(() => {
  // 取消Promise
  testPromise.cancel()
}, 1000)

可以看到正常使用和原生Promise并无区别,但是新增了onCancel、cancel、config等Api,简单介绍下

  • cancel:用于取消当前Promise
  • onCancel:Promise取消后会调用传入该方法的回调
  • isCancelled:判断Promise是否取消
  • config:配置项,因为取消Promise在当前版本中是默认关闭、传入cancellation: true打开取消功能

中文文档可以关注这里

总结与对比

在前端开发中,取消 Promise 操作是处理异步流程控制的重要能力。以下是各方案的对比:

方案对比

方案 优点 缺点 适用场景
Promise.race() 纯 JavaScript 实现,无需额外库 只是"模拟"取消,实际异步操作仍在执行 简单的取消需求,兼容性要求高
AbortController 原生支持,与 fetch API 深度集成 较新的 API,需要 polyfill 网络请求取消,现代浏览器项目
Bluebird 功能丰富,API 完善 需要引入第三方库,增加包体积 需要高级 Promise 功能的复杂应用

实践建议

  1. 现代项目首选 AbortController - 随着原生支持的普及,这是最标准和推荐的方式
  2. 简单场景用 Promise.race() - 对于简单的取消需求,这种方式足够且轻量
  3. 复杂异步流程考虑 Bluebird - 如果需要进度追踪、超时控制等高级功能

注意事项

  • 取消 Promise 并不意味着底层操作真的停止了(如定时器)
  • 要及时清理资源,避免内存泄漏
  • 在 React/Vue 等框架中,组件卸载时务必取消未完成的异步操作

选择合适的方法取决于具体需求、浏览器兼容性要求和项目架构。

相关推荐
w2sfot39 分钟前
【JS加密在线】jsjiami.online(让JavaScript 更安全!)
开发语言·javascript·安全
HSunR40 分钟前
ruoyi 若依 自定义注解 参数校验
java·前端·数据库
拆房老料2 小时前
ONLYOFFICE也能像Microsoft Word和WPS一样分别设置中西文字体
前端·html·word·开源软件·wps
Solis程序员2 小时前
Stripe 幂等表:把「不确定的重试」变成「查表返回」
前端·安全·bootstrap·php·agent
李纲明2 小时前
WordPress 站点变慢:按 TTFB → 缓存 → 查询 → 前端 分层排查(含配置注意)
前端·缓存·性能优化·wordpress·后端开发
程序人生8882 小时前
PDF 转 Word 版式错乱、表格丢失?DocConverter Web 格式互转引擎的保真实践
前端·人工智能·opencv·机器学习·pdf·word
粥里有勺糖3 小时前
安利一下最近用的桌面“Agent” | T3 Code
前端·github·ai编程
xy34533 小时前
Axure 9.0 动态面板基本操作
前端·ui·html·axure·原型·产品设计
不停喝水4 小时前
【前端转全栈java速通课】 项目实战④7-11节 操作数据库-登录-注册-修改密码-注销-mubatis-plus简化crud-
java·前端·数据库
一水鉴天4 小时前
统一对象拓扑(UOT)设计全链定稿:从三件事分离到三继承 之1 20261010(豆包“查看聊天内容”继续)
前端·css