为什么说promise不能取消是一个缺点

发布于 2022-09-05 01:38:28 字数 94 浏览 24 评论 0

什么场景下我需要取消一个promise?
我不理解的地方:
http是无状态的,那取消是不是意味着新的请求?
还是说取消仅是本地取消,不处理之前请求的结果?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

青春如此纠结 2022-09-12 01:38:28

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?

这是一道送命题啊。

巷雨优美回忆 2022-09-12 01:38:28

@ewind @lzszone cancel promise 是有的。。。不过跟很多人理解的 cancel 是不同的。。。已经发生的操作是不能 cancel 的,要 cancel 也只是 cancel 这个操作本该有的后续操作。。。

例如我本来要 fetch(url) 得到响应 resp 后,根据 resp 的内容修改一个变量。。。
代码是:fetch(url).then(resp => global.something = resp.xxx);

然后我要把这个操作 cancel 掉,应该:

var p = make_cancelable(fetch(url));
p.then(resp => global.something = resp.xxx);
do_something();
p.cancel();

这里,请求发送是免不了的。。。但是得到响应后,我们可以忽略这个响应,让它不修改那个变量。。。这就是promise 的 cancel。。。

最简单,但有一些副作用的 make_cancelable 实现是:

function cancelable(promise) {
    let cancel = false;
    let p = promise.then(val => {
        if (cancel) {
            throw cancelable.cancel_error;
        }
        return val;
    });
    p.cancel = () => cancel = true;
    return p;
}
cancelable.cancel_error = new Error('promise canceled.');

另外有个基本完美的 cancelable_promise 实现。。。
https://github.com/hjylewis/t...

具体的关于 cancelable_promise 的讨论可以看
https://github.com/facebook/r...
这是 react 的 this.isMounted api 的讨论,里面有使用 cancelable_promise 来解决去掉该 api 后会引起的问题。。。

微凉徒眸意 2022-09-12 01:38:28

比如页面需要1分钟刷新一次,但是接口特别慢,所以导致我下次发送请求的时候,上次的请求还没有回来,在这种情况下我就想取消上次的请求。

蓝天白云 2022-09-12 01:38:28

同时进行两个操作(两个Promise),其中一个完成了就把另一个取消掉,最后返回先成功的结果。

但是取消都是坑,例如多线程做取消意味着异步异常,就是操作到一半突然被打断, 很难进行恢复或者回滚。只有纯CPU的独立的计算任务才能安全地取消。

至于取消然后取消“取消”是不会有的,规矩进入cancel状态(半死不活状态)就不能切换到其他状态就行了。

猫瑾少女 2022-09-12 01:38:28

比如点赞,取消点赞操作
如果是使用promise当你误点赞了你想点取消赞时, 你就必须等点赞操作结束才能操作
所以有了加强版的promise → observable

多孤肩上扛 2022-09-12 01:38:28

promise不应该被cancel,否则应该用rxjs来描述行为。
否则各种奇怪的边界情况根本无法处理。

毅然前行 2022-09-12 01:38:28

https://www.npmjs.com/package...
区别对待 cancel 和 reject,以免入坑

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文