百科问答小站 logo
百科问答小站 font logo



Promise 不能被取消,真的算是它的缺点吗? 第1页

  

user avatar   catchen 网友的相关建议: 
      

不是。TC39 曾经有人提案过取消 Promise 的 API,但最后讨论一番后作者撤销了提案。以下是 TC39 GitHub 上的提案:

已经有人写过长文为什么 Promise 不应该有可取消的 API:

根据 TC 历史讲故事的工作交给 @贺师俊 吧,我直接说一下为什么 Promise 不能被取消吧。


首先,Promise 被设计为 eager,也就是一旦启动就立即开始执行,尽快获得执行结果,而不是等到你需要结果时才开始执行。这种设计使得 Promise 的取消往往毫无意义。

这种 eager 执行的方式,就如同你下单后立即现金结算然后发货一样,钱你肯定是要不回来的,货物送到后你也不可能要求送回仓库去,你拒收就相当于把货物在原地扔掉。

类似地,Promise 一旦开始执行,底层的软硬件资源开销就已经产生了,没有任何办法撤回。举个具体的例子,你发了一个网络请求,无论如何这个网络请求都会发完,无论如何服务器返回的数据都会收完,底层不提供任何接口给你中断和服务器的连接。

所以,如果你取消 fetch 返回的 Promise 实际上什么都撤销不了。上层调用 fetch 的复杂异步操作,给你一个可取消的 Promise,实际上也是无法撤销底层的 fetch。如果复杂操作涉及多次 fetch,让你取消实际上撤销了哪个 fetch,哪个 fetch 已经撤销不了,也无法明示。

如果取消 Promise 的语义如此不明确,那还是别给你取消的 API 好了。


要有明确的可撤销语义,很快你发现你重新发明了 Observable,那你为什么不直接用 Observable 呢?

回到上面的例子,你有一个复杂的异步操作,需要多阶段调用 fetch,封装成 Observable 就可以一步一步往前走,你不让它往前走时,剩余步骤的开销就不会发生。所谓的取消,就是不再驱动它往前走,这一个变量就能控制。


在 Promise 广泛应用之后,再引入取消的 API 就会破坏兼容性。一个 Promise 启动后,原本 await 只预期 resolve 或 reject 两种终极状态。现在多一个 cancel 的终极状态,原来的代码处理不了,怎么办?

你会说你不取消 Promise 就能保证兼容,但你能保证你写的 Promise 内部嵌套的别人的 Promise 呢?例如一个第三方库,支持取消当前所有网络请求的 Promise,你怎么办?


如果你真的需要一个可以取消的 Promise,你用两个正常的 Promise 就能捏出来一个。第一个 Promise 是正常使用的 Promise,代表你要执行的异步操作状态。第二个 Promise 代表第一个 Promise 是否被取消过,取消时它就 resolve,但一旦第一个 Promise 完成了它就被自动 reject 掉。这时候你就手工捏出来了一个有三个终极状态的 Promise。




  

相关话题

  C#相对路径 连接Access数据库怎么写?? 
  为什么 Java 和 JS 等语言需要 VM,不能直接操作内存堆栈空间? 
  es,js,ts三者有什么关系? 
  从事前端真的没有后端工资高? 
  2022 年,学完 JS 高级后的学习路线怎样规划? 
  当人们说一个前端框架太“厚重”时,他们在说什么? 
  大公司实习经历对下一份工作能带来多少帮助? 
  如何评价 Typescript 的运行时类型检测工具io-ts? 
  为什么说js中的array不是真array,class不是真class? 
  鸿蒙 OS 的多端自动适配功能,是不是夸张了? 

前一个讨论
资本家为了盈利不是不惜一切代价吗?那为什么作为工业品的显卡他们不愿扩大产量呢?
下一个讨论
为什么CPU/GPU的温度会在一瞬间波动十度以上?





© 2025-05-06 - tinynew.org. All Rights Reserved.
© 2025-05-06 - tinynew.org. 保留所有权利