百科问答小站 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。




  

相关话题

  已经 2022 年了,学习 JavaScript 继承方式的意义是什么? 
  美国国会举行听证会讨论 「Web3.0」,目前技术发展状况如何?未来可能在哪些领域带来新发展? 
  chrome41.0.2224.3版本的知乎顶部条为什么显示不正常? 
  Flutter 革命性的地方在哪里? 
  国内做前端年薪有上50W的吗? 
  浏览器根据charset判断编码方式的疑问? 
  不太理解预防csrf攻击中的“双提交cookie”是什么意思? 
  React.js有哪些设计缺陷? 
  前端嫌我接口分的太多,我该怎么回答? 
  有多大比例的前端工程师,能在合理的时间内独立开发出一个足以供商业网站使用的文本编辑器? 

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





© 2024-11-08 - tinynew.org. All Rights Reserved.
© 2024-11-08 - tinynew.org. 保留所有权利