什么场景下我需要取消一个promise?
我不理解的地方:
http是无状态的,那取消是不是意味着新的请求?
还是说取消仅是本地取消,不处理之前请求的结果?
什么场景下我需要取消一个promise?
我不理解的地方:
http是无状态的,那取消是不是意味着新的请求?
还是说取消仅是本地取消,不处理之前请求的结果?
@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 后会引起的问题。。。
同时进行两个操作(两个Promise),其中一个完成了就把另一个取消掉,最后返回先成功的结果。
但是取消都是坑,例如多线程做取消意味着异步异常,就是操作到一半突然被打断, 很难进行恢复或者回滚。只有纯CPU的独立的计算任务才能安全地取消。
至于取消然后取消“取消”是不会有的,规矩进入cancel状态(半死不活状态)就不能切换到其他状态就行了。
8 回答4.7k 阅读✓ 已解决
6 回答3.4k 阅读✓ 已解决
5 回答2.8k 阅读✓ 已解决
5 回答6.3k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
3 回答2.4k 阅读✓ 已解决
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?
这是一道送命题啊。