Bluebird 弃用 API 完全指南:Progression、Promise.defer 与旧版取消语义的迁移实战

发布时间:2026/11/12 18:03:35

Bluebird 弃用 API 完全指南:Progression、Promise.defer 与旧版取消语义的迁移实战 Bluebird 弃用 API 完全指南Progression、Promise.defer 与旧版取消语义的迁移实战【免费下载链接】bluebird:bird: :zap: Bluebird is a full featured promise library with unmatched performance.项目地址: https://gitcode.com/gh_mirrors/bl/bluebird本文以 Bluebird 官方弃用文档docs/docs/deprecated-apis.md为骨架系统梳理三类已被弃用但仍可运行的 API——旧式进度ProgressionAPI、Promise.defer/PromiseResolver解析器模式、以及 2.x 时代的旧版取消语义。文章逐一说明每类 API 的调用形态、废弃原因、底层源码证据并给出迁移到new Promise、tap、Promise.coroutine与 3.x 新取消模型的完整实战方案。读完本文你将能识别存量代码中的弃用写法并安全、平滑地将其改写为官方推荐的新式写法。一、概述什么是 Bluebird 的弃用 API为何仍有价值Bluebird 的弃用 API 有两条明确的界定仍然可以正常工作——弃用不等于立即失效存量代码在新版本中依旧能运行将在未来的某个版本中被移除——官方已明确这些 API 不再受支持新代码不应再使用。针对这些弃用方法所解决的每一个使用场景官方 API 参考中都存在更好的替代方案请优先参考 API Reference。当前仓库的弃用 API 集中在三大类类别涉及 API推荐替代Progression旧进度.progressed(handler)、.then第三参数、.done第三参数tap、Promise.coroutine、外部IProgress回调Promise resolution解析器Promise.defer/Promise.pending、resolver.resolve/reject/progressnew Promise((resolve, reject) …)Old Promise Cancellation旧取消2.x 的 abort 语义取消3.x 新取消模型onCancel dont care 语义从源码看弃用并非停留在文档层面。在 src/debuggability.js 中Bluebird 实现了统一的弃用告警机制function deprecated(name, replacement) { var message name is deprecated and will be removed in a future version.; if (replacement) message Use replacement instead.; return warn(message); }也就是说当你在代码中调用Promise.defer()等弃用 API 时在启用警告配置的前提下见 promise.config运行时会在控制台输出类似Promise.defer is deprecated and will be removed in a future version. Use new Promise instead.的提示帮助开发者逐步识别并清理存量代码。二、Progression旧式进度追踪 API 的完整剖析2.1 设计初衷与失败原因旧的 Progression API 本意是追踪 promise 解析过程的进度例如异步下载的百分比。官方在弃用文档中直言事后回顾这套 API既不好用组合性compose也很差——因为进度事件无法像值传递那样自然地沿 promise 链传播导致链式调用与并行组合场景下行为诡异。官方对问题的理解已经足够透彻这一使用场景完全可以不用它来解决。2.2 三个被弃用的具体形态.progressed(Function handler)-Promise.progressed(handler)是.then(null, null, handler)的简写形式为该 promise 附加一个进度处理器当 promise 被进度化progressed时调用。它返回一个新的 promise可继续链式调用promise .progressed(function(percent) { console.log(下载进度: percent %); }) .then(function(data) { // 处理最终结果 });.then([fulfilledHandler] [, rejectedHandler] [, progressHandler])-PromiseBluebird 对 Promises/A 标准.then()的支持是无限期保留的——标准的两参数形式永远不会弃用。被弃用的只是接受第三个progressHandler参数的变体// 弃用写法第三个参数是进度处理器 promise.then(onFulfilled, onRejected, onProgress); // 保留写法标准两参数形式 promise.then(onFulfilled, onRejected);.done([fulfilledHandler] [, rejectedHandler] [, progressHandler])-void.done()与.then()类似但若链上最终存在未处理的 rejection会直接以异常形式抛出而不是静默丢失。同样只有带进度处理器的变体被弃用.done()本身在 Bluebird 中仍完全受支持// 弃用写法 promise.done(onFulfilled, onRejected, onProgress); // 仍然支持 promise.done(onFulfilled, onRejected);2.3 从源码看进度 API 的归宿在 3.x 版本的 src 目录中对progressed、progressHandler、_progress等符号进行全量检索已找不到任何实现——这印证了弃用文档的判断进度 API 在 3.x 中已被彻底移除存量代码必须依赖迁移方案改造后才能运行。三、Progression 迁移实战三种官方推荐的替代模式Bluebird 提供了专门的迁移指南progression-migration。其核心思路是把进度事件从 promise 机制中剥离出来改为通过普通回调参数显式传递。下面三种模式覆盖了绝大多数使用场景。3.1 场景一jQuery 风格的进度回调迁移前使用.progressedPromise.resolve($.get(...)) .progressed(function() { // ... }) .then(function() { // ... }) .catch(function(e) { // ... });迁移后把进度回调交给底层操作本身Promise.resolve($.get(...).progress(function() { // ... })) .then(function() { // ... }) .catch(function(e) { // ... });关键区别进度回调不再挂在 promise 链上而是挂在产生 promise 的异步操作此处是 jQuery 的$.get上promise 链只承载最终的完成值与错误。3.2 场景二C#IProgress风格的通用进度接口借鉴 C# 中IProgress的模式用tap在链式执行的各阶段插入进度回调tap的语义是执行副作用但不改变传递的值function returnsPromiseWithProgress(progressHandler) { return doFirstAction().tap(function() { progressHandler(0.33); }).then(doSecondAction).tap(function() { progressHandler(0.66); }).then(doThirdAction).tap(function() { progressHandler(1.00); }); } returnsPromiseWithProgress(function(progress) { ui.progressbar.setWidth((progress * 200) px); // 在客户端更新进度条宽度 }).then(function(value) { // 全部动作完成 // 整条链完成 }).catch(function(e) { // 错误处理 });3.3 场景三Promise.coroutine生成器协程中的进度协程把异步流程写成同步代码进度回调以普通参数形式注入可读性极佳var doNothing function() {}; var progressSupportingCoroutine Promise.coroutine(function* (progress) { progress typeof progress function ? progress : doNothing; var first yield getFirstValue(); // 33% 完成 progress(0.33); var second yield getSecondValue(); progress(0.67); var third yield getThirdValue(); progress(1); return [first, second, third]; }); var progressConsumingCoroutine Promise.coroutine(function* () { var allValues yield progressSupportingCoroutine(function(p) { ui.progressbar.setWidth((p * 200) px); }); var second allValues[1]; // ... });关于.tap与协程的更多细节可分别参考 tap 与 Promise.coroutine。四、Promise resolutionPromise.defer与旧式PromiseResolver4.1PromiseResolver是什么PromiseResolver用于从外部控制一个 promise 的最终命运功能上等价于 jQuery 的 Deferred 或 Angular$q的$q.defer。关键特征每个PromiseResolver对象带有一个.promise属性返回被控制 promise 的引用可安全地交给客户端与其它实现不同Bluebird 的.promise是普通属性而非 getter 函数写法上不需要加括号一旦底层 promise 的命运已定被跟随、被拒绝、被完成resolver 上的所有方法均不再生效即后续调用被静默忽略。其典型用法取自弃用文档中的完整示例function delay(ms) { var resolver Promise.defer(); var now Date.now(); setTimeout(function(){ resolver.resolve(Date.now() - now); }, ms); return resolver.promise; } delay(500).then(function(ms){ console.log(ms ms passed); });4.2 Resolver 的三个方法方法签名语义.resolve(value).resolve(dynamic value) - undefined以value解析底层 promise若value是 thenable 或 promise底层 promise 将采用其状态跟随.reject(reason).reject(dynamic reason) - undefined以reason拒绝底层 promise.progress(value).progress(dynamic value) - undefined以value推进底层 promise 的进度属于被弃用的进度机制一部分4.3 源码中的真实实现与弃用告警在 src/promise.js 中可以看到Promise.defer的完整实现function deferResolve(v) {this.promise._resolveCallback(v);} function deferReject(v) {this.promise._rejectCallback(v, false);} Promise.defer Promise.pending function() { debug.deprecated(Promise.defer, new Promise); var promise new Promise(INTERNAL); return { promise: promise, resolve: deferResolve, reject: deferReject }; };几个值得注意的实现细节Promise.defer与Promise.pending是同一个函数的别名二者完全等价每次调用都会触发debug.deprecated(Promise.defer, new Promise)告警明确指向替代方案3.x 的 resolver 对象只有promise、resolve、reject三个成员——progress方法已随进度机制一并移除在 src/constants.js 中还有一条相关的错误提示UNBOUND_RESOLVER_INVOCATION其文案为Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.进一步印证官方对 resolver 模式的整体态度。另外值得注意的是在 test/mocha 的大量测试文件如 api_exceptions.js、bind.js、async.js中仍能看到Promise.defer()的广泛使用——这说明即便在官方测试套件中defer 模式在测试隔离、手动控制完成时机这类场景下仍是实用工具但对新写的应用代码官方强烈不推荐。4.4 为什么不推荐Promise.defer从反模式到新式写法弃用文档给出了明确的判断使用Promise.defer和 deferred 对象是被劝阻的——它比使用new Promise笨拙得多也更容易出错。defer 模式的经典反模式是先创建 resolver再在多个回调里散落地调用resolve/reject容易造成忘记在错误路径上调用reject导致 promise 永远挂起过早把 resolver 暴露给多个模块使谁能完成这个 promise变得不可控。推荐的新式写法见 new-promise// 弃用写法 function delay(ms) { var resolver Promise.defer(); var now Date.now(); setTimeout(function(){ resolver.resolve(Date.now() - now); }, ms); return resolver.promise; } // 推荐写法executor 函数把 resolve/reject 封闭在创建作用域内 function delay(ms) { var now Date.now(); return new Promise(function(resolve) { setTimeout(function(){ resolve(Date.now() - now); }, ms); }); } delay(500).then(function(ms){ console.log(ms ms passed); });executor 模式将 promise 的创建与完成收拢在同一处错误路径reject与成功路径resolve一目了然从根本上消除了 resolver 泄漏与未决 promise 的风险。五、Old Promise Cancellation2.x 旧取消语义与新模型对比5.1 为什么旧的取消语义被推翻2.x 时代的 promise 取消采用abort 语义取消一个 promise 即中止它所代表的底层操作。官方认为这套语义不健全因此在3.x 中对取消功能进行了彻底重构major overhaul目标是建立一种健全的sound可取消 promise 模型。如果你的存量代码依赖 2.x 的取消语义它无法直接在 3.x 中工作。2.x 的取消功能仍可在 bluebird 2.x 上使用该分支仍受支持但官方不推荐2.x 的文档仍可访问。3.x 新取消模型的完整说明见 Cancellation。5.2 3.x 新取消模型的核心变化维度2.x 旧模型abort 语义3.x 新模型dont care 语义取消含义中止底层操作仅表示该 promise 的处理器回调不再被调用[.cancel()](https://link.gitcode.com/i/b8e710b83c7ceef8b439fe2370430c14)是否同步否是同步需要额外设置代码需要不需要与其他特性组合差好如与 Promise.all 良好组合多消费者场景语义模糊有合理语义所有消费者都取消时才向上传播取消信号取消钩子—可选优化executor 的onCancel参数新模型的关键设计来自 cancellation取消功能默认关闭需通过 Promise.config 显式启用cancel()同步返回但onCancel钩子与then处理器一样在下一轮事件循环异步调用onCancel是可选的、断开连接的优化——不注册任何取消钩子取消也能正常工作只是无法中止底层网络请求等操作但这不影响正确性因为回调同样不会被调用相应地onCancel内部抛出的错误不会被捕获并转为 rejection多消费者语义result会记录消费者数量例如result.then(...)两次即为 2只有当所有消费者都发出取消时取消信号才会向上传播、触发底层 abort对单个消费者而言其 promise 已成功取消、处理器不会被调用。此外消费一个已取消的 promise 是错误的会得到一个以new CancellationError(late cancellation observer)拒绝的 promise。新模型下注册取消钩子的推荐写法function makeCancellableRequest(url) { return new Promise(function(resolve, reject, onCancel) { var xhr new XMLHttpRequest(); xhr.on(load, resolve); xhr.on(error, reject); xhr.open(GET, url, true); xhr.send(null); // 注意仅当启用取消功能时onCancel 参数才存在 onCancel(function() { xhr.abort(); }); }); }一个典型的搜索框防抖场景来自官方文档var searchPromise Promise.resolve(); // 占位 promise避免空值判断 document.querySelector(#search-input).addEventListener(input, function() { // 上一次请求的处理器必须不再被调用 searchPromise.cancel(); var url /search?term encodeURIComponent(this.value.trim()); showSpinner(); searchPromise makeCancellableRequest(url) .then(function(results) { return transformData(results); }) .then(function(transformedData) { document.querySelector(#search-results).innerHTML transformedData; }) .catch(function(e) { document.querySelector(#search-results).innerHTML renderErrorBox(e); }) .finally(function() { // 这个判断是必要的因为 .finally 处理器总是会被调用 if (!searchPromise.isCancelled()) { hideSpinner(); } }); });注意取消发生后finally与reflect()的处理器仍会被调用用于清理而then(onSuccess, onFailure)中的两个处理器都不会被调用——这类似于Generator#return的行为只执行活动的finally块随后生成器退出。六、迁移路线图与自检清单把三部分内容整合为一张迁移速查表存量代码特征弃用 API迁移动作出现.progressed(...)Progression改用tap或外部进度回调见 progression-migration.then(a, b, c)带第三参数带进度变体.then移除第三参数只保留标准两参数形式.done(a, b, c)带第三参数带进度变体.done移除第三参数.done本身继续可用Promise.defer()/Promise.pending()Promise resolution改写为new Promise(executor)见 new-promiseresolver.progress(value)Promise resolution该 API 已移除随进度机制一并迁移依赖 2.x abort 语义的取消代码Old cancellation升级到 3.x 新取消模型需Promise.config启用见 cancellation 与 promise.config迁移完成后的自检要点全文检索在代码库中搜索progressed、.then(a, b, c)三参形式、Promise.defer、Promise.pending、resolver.progress等特征确认零残留观察运行时告警在启用警告配置时运行测试与开发环境检查控制台是否出现is deprecated and will be removed in a future version类提示验证取消行为若使用取消功能确认Promise.config已启用取消并针对多消费者取消消费已取消 promise等边界编写针对性测试回归测试仓库 test/mocha 中的api_exceptions.js、bind.js、async.js、cancel.js等用例可作为行为基准验证迁移后语义一致。结语Bluebird 对弃用 API 的处理展示了一条健康的演进路径旧 API 保留运行以照顾存量代码同时通过运行时告警与详尽的迁移文档引导开发者走向更健全的新模型。Progression 被外部回调 tap 协程取代Promise.defer被new Promiseexecutor 取代2.x abort 语义的取消被 3.x 的 dont care 语义取代——这三条迁移路线本质上都是把副作用与状态从 promise 机制中剥离让 promise 链只承担最纯粹的值传递与错误传播职责。如果你正在维护使用了这些旧 API 的存量代码按照本文的速查表逐项改造即可平滑过渡到官方推荐的现代写法。【免费下载链接】bluebird:bird: :zap: Bluebird is a full featured promise library with unmatched performance.项目地址: https://gitcode.com/gh_mirrors/bl/bluebird创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/12 18:03:34

单相电参数测量仪设计:真有效值、功率因数与同步采样

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/7 10:21:01

BrewUI:给Homebrew套上可视化外衣,让Mac包管理更直观

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/7 12:46:37

运维简历PDF解析与ATS关键词优化:从pdftotext到面试自检

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/12 18:02:36

广东地区电工证怎么考 上岗必备全流程避坑指南

广东地区电工证怎么考 上岗必备全流程避坑指南 你是不是也这样?刚毕业或打算转行,听说电工证是 上岗必备 ,可又不知道去哪儿报名,怕被中介坑,担心交了钱拿不到证?别急,这篇文章就为你把广东地区电工证怎么考的每一步讲清楚,从报名到考试,从复习到…

2026/11/12 18:02:36

高压电工证哪个部门真实经历:三门峡学员避坑全流程解析

高压电工证哪个部门真实经历:三门峡学员避坑全流程解析 别再被中介忽悠了,高压电工证哪个部门能办,很多人一开始就被绕进去了。我身边就有个同事,跑了好几趟,结果白花了钱,连证都没拿到。今天我就从三门峡培训机构学员的角度,分享我真实的经历,告诉你…

2026/11/12 18:02:36

江门电工证通过率高吗在哪考最稳妥

江门电工证通过率高吗在哪考最稳妥 之前考的证在外省能不能转过来?这个问题几乎每个准备在江门报考电工证的人都会问。其实,江门作为广东省的一个重要城市,不仅本地从业者多,外来务工人员也很多,很多人在外省考过的证书,只要符合相关要求,是可以在江门…

2026/11/12 17:57:36

东莞电工证复审考试千万别踩坑,怕考不过白交培训费?

东莞电工证复审考试千万别踩坑,怕考不过白交培训费? 你是不是正准备参加东莞电工证复审考试?怕考不过白交培训费?别急,我从业这么多年,见过太多人因为踩坑而白白浪费钱和时间,今天就把这些经验掏心窝子告诉你,看完你就能少走弯路!…

2026/11/11 12:42:59

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/12 0:04:01

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘 工地太忙根本没时间复习考试?你不是一个人。作为一名在南阳卧龙区干了七八年市政公用工程的电工,我深知这个问题的现实性。电工证不仅是工作的“入场券”,更是职业发展的“通行证”,但备考过程…

2026/11/12 0:04:01

双流电工证考别怕挂科!郑州报考避坑指南全攻略

双流电工证考别怕挂科!郑州报考避坑指南全攻略 实操考试心里没底怕挂科?双流电工证考在郑州报名,很多人因为不了解流程、准备不充分,白白浪费时间和金钱。作为三门峡应届工程类毕业生,我也曾经历过这样的焦虑。今天就从零开始,手把手教你如何避开郑州报…

2026/11/12 0:04:01

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少 之前考的证在外省能不能转过来?这个问题确实让不少准备换城市工作的朋友犯了难,尤其像电工证这种实操性很强的证书,很多人担心跨省后证书能不能继续用。其实,只要符合相关流程,是可以顺利转…

2026/11/11 20:27:01

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/12 9:51:42

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑