如何使用Bluebird取消Promise?测试用例未通过求修正
问题分析与解决方案
你遇到的核心问题是原生Promise不支持取消机制,而且你没有正确配置Bluebird的取消功能,也没有在异步操作中处理取消时的资源清理。下面一步步帮你修改测试用例:
关键修改点
- 必须使用Bluebird的Promise实例(而非原生Promise),并启用取消配置
- 在异步任务中添加
onCancel回调,清理资源(比如定时器),确保取消真正终止异步操作 - 验证取消时的错误类型,确保流程符合预期
修改后的完整测试代码
describe('cancellation tests', () => { const Promise = require('bluebird'); // 启用Bluebird的取消机制,这是前提! Promise.config({ cancellation: true }); function fakeFetch() { // 使用Bluebird的Promise构造函数,第三个参数是onCancel回调 return new Promise((resolve, reject, onCancel) => { const timer = setTimeout(() => { resolve(1); }, 100); // 当Promise被取消时,清理定时器,终止异步操作 onCancel(() => { clearTimeout(timer); }); }); } function awaitAndAddOne(p1) { // p1是Bluebird Promise,then返回的也是Bluebird Promise,链式可取消 return p1.then(res => res + 1); } it('`cancel` cancels promises higher up the chain', () => { const p1 = fakeFetch(); const p2 = awaitAndAddOne(p1); expect(p2.isCancellable()).toBeTruthy(); p2.cancel(); return p2 .then(() => { // 如果取消成功,这个then分支不应该执行 throw new Error('Promise should have been cancelled'); }) .catch(err => { // 验证取消抛出的是Bluebird的CancellationError expect(err instanceof Promise.CancellationError).toBeTruthy(); }) .finally(() => { expect(p2.isCancelled()).toBeTruthy(); expect(p1.isCancelled()).toBeTruthy(); }); }); });
为什么这样修改?
- 启用取消配置:Bluebird的取消功能默认是关闭的,必须通过
Promise.config({ cancellation: true })开启。 - 替换原生Promise:原生Promise没有
isCancellable()、isCancelled()和cancel()方法,必须全程使用Bluebird的Promise实例。 - onCancel资源清理:如果不清理定时器,即使调用了
cancel(),定时器到期后Promise依然会resolve,导致isCancelled()返回false。onCancel回调能让我们在取消时终止异步操作。 - 链式取消传播:Bluebird的取消机制会自动向上传播,取消
p2时会自动标记上游的p1为已取消,只要整个链都是Bluebird Promise。
内容的提问来源于stack exchange,提问作者vonovak
相关产品推荐
相关产品推荐

