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




  

相关话题

  如何看待 node-ipc 包以反战为名进行供应链投毒? 
  如何评价微信小程序内嵌网页功能开放? 
  如何去判断 JS 字符串中含某个字符串? 
  前端现在怎么这么多人? 
  所谓的几年编程经验,潜台词指的是什么? 
  作为一名 App 开发者,你是如何看待字节跳动剥离 TikTok 美国业务一事的? 
  为什么维基百科的用户界面设计不够友好? 
  请问一下各位大佬,js的静态方法有啥作用呀,写工具类吗,小菜鸡想不出来静态方法有啥作用? 
  为什么 JS 不能绕过后端代码直接调数据库,有哪些后端处理的逻辑,JS 不能写? 
  有哪些效果拔群的 WebAssembly 应用? 

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





© 2024-12-22 - tinynew.org. All Rights Reserved.
© 2024-12-22 - tinynew.org. 保留所有权利