为什么说promise不能取消是一个缺点
什么场景下我需要取消一个promise?
我不理解的地方:
http是无状态的,那取消是不是意味着新的请求?
还是说取消仅是本地取消,不处理之前请求的结果?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
什么场景下我需要取消一个promise?
我不理解的地方:
http是无状态的,那取消是不是意味着新的请求?
还是说取消仅是本地取消,不处理之前请求的结果?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(7)
Promise 的设计就是一个状态机,pending 到 resolve / reject 的状态变换是单向且唯一的,没有所谓的 cancel 状态。cancel 的加入会带来更多的状态问题,并不适合 Promise 这一模式来处理(这类场景下,RxJS 这类 FRP 的方案应该更为适合)。
cancel 会带来什么状态问题呢?拿电商的退款来举例子。你买了一个东西(开始一个 pending 的 promise),然后东西还没收到(还没 resolve),你后悔了,点击了退款(把状态改为 cancel),但这时退款流程也不能立刻生效,需要审核(cancel 后不能立刻 reject),那这时候你发工资了,又不想退款了,又点了【取消退款】,这时候又是一个异步的状态更改(把 cancel 再 cancel 掉),而【取消退款】也是异步的,你还能取消【取消退款】的操作(把 cancel 在 cancel 掉前再 cancel 掉?)别忘了,这时候每一步状态变化还都可以对应到 resolve 和 reject 呢。好的同学们,接下来请画出流程的状态变化图,并编码实现这个支持 cancel 的 promise?
这是一道送命题啊。
@ewind @lzszone cancel promise 是有的。。。不过跟很多人理解的 cancel 是不同的。。。已经发生的操作是不能 cancel 的,要 cancel 也只是 cancel 这个操作本该有的后续操作。。。
例如我本来要 fetch(url) 得到响应 resp 后,根据 resp 的内容修改一个变量。。。
代码是:
fetch(url).then(resp => global.something = resp.xxx)
;然后我要把这个操作 cancel 掉,应该:
这里,请求发送是免不了的。。。但是得到响应后,我们可以忽略这个响应,让它不修改那个变量。。。这就是promise 的 cancel。。。
最简单,但有一些副作用的 make_cancelable 实现是:
另外有个基本完美的 cancelable_promise 实现。。。
https://github.com/hjylewis/t...
具体的关于 cancelable_promise 的讨论可以看
https://github.com/facebook/r...
这是 react 的 this.isMounted api 的讨论,里面有使用 cancelable_promise 来解决去掉该 api 后会引起的问题。。。
比如页面需要1分钟刷新一次,但是接口特别慢,所以导致我下次发送请求的时候,上次的请求还没有回来,在这种情况下我就想取消上次的请求。
同时进行两个操作(两个Promise),其中一个完成了就把另一个取消掉,最后返回先成功的结果。
但是取消都是坑,例如多线程做取消意味着异步异常,就是操作到一半突然被打断, 很难进行恢复或者回滚。只有纯CPU的独立的计算任务才能安全地取消。
至于取消然后取消“取消”是不会有的,规矩进入cancel状态(半死不活状态)就不能切换到其他状态就行了。
比如点赞,取消点赞操作
如果是使用promise当你误点赞了你想点取消赞时, 你就必须等点赞操作结束才能操作
所以有了加强版的promise → observable
promise不应该被cancel,否则应该用rxjs来描述行为。
否则各种奇怪的边界情况根本无法处理。
https://www.npmjs.com/package...
区别对待 cancel 和 reject,以免入坑