無(wú)法取消 Promise

Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。
所謂Promise,簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語(yǔ)法上說(shuō),Promise 是一個(gè)對(duì)象,從它可以獲取異步操作的消息。Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進(jìn)行處理。
(1)對(duì)象的狀態(tài)不受外界影響。Promise 對(duì)象代表一個(gè)異步操作,有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和 rejected(已失敗)。只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無(wú)法改變這個(gè)狀態(tài)。這也是 Promise 這個(gè)名字的由來(lái),它的英語(yǔ)意思就是“承諾”,表示其他手段無(wú)法改變。
(2)一旦狀態(tài)改變,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果。Promise對(duì)象的狀態(tài)改變,只有兩種可能:從 pending 變?yōu)?fulfilled 和從 pending 變?yōu)?rejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會(huì)再變了,會(huì)一直保持這個(gè)結(jié)果,這時(shí)就稱為 resolved(已定型)。如果改變已經(jīng)發(fā)生了,你再對(duì) Promise 對(duì)象添加回調(diào)函數(shù),也會(huì)立即得到這個(gè)結(jié)果。這與事件(Event)完全不同,事件的特點(diǎn)是,如果你錯(cuò)過(guò)了它,再去監(jiān)聽(tīng),是得不到結(jié)果的。
Promise 也有一些缺點(diǎn)。首先,無(wú)法取消 Promise,一旦新建它就會(huì)立即執(zhí)行,無(wú)法中途取消。
Promise 不能被取消,真的算是它的缺點(diǎn)嗎?
其實(shí)還好,多數(shù)情況下,我們要取消的不是 Promise,而是生成 Promise 的那個(gè)任務(wù)。
而且這個(gè)任務(wù)本身的取消,有時(shí)還附帶清理現(xiàn)場(chǎng)的需求,比方說(shuō),我 await 了一個(gè)存儲(chǔ)文件的任務(wù),那么取消這個(gè)存儲(chǔ)文件任務(wù),意味著中斷文件寫入,把已經(jīng)寫入的一些信息回滾等等操作。單純從 Promise 的角度取消,其實(shí)只是取消了 Promise 后的回調(diào),原本的任務(wù)還是執(zhí)行完成了,若真設(shè)計(jì)出取消功能,很容易造成誤判。
此外,當(dāng)真正需要取消時(shí),我們完全可以在 await 之后或者 then 的回調(diào)中加入控制邏輯,這能夠保證代碼邏輯緊湊,否則,我們調(diào)試時(shí)可能面臨“ Promise 被取消時(shí)到處找取消的代碼”這樣的窘境。
綜上,我認(rèn)為 Promise 的取消功能不能說(shuō)完全沒(méi)用,至少在我看來(lái)沒(méi)什么必要性,甚至不是什么好的實(shí)踐。不能被取消,更談不上設(shè)計(jì)缺點(diǎn)了。
我們多數(shù)情況下需要取消語(yǔ)義是為了通過(guò)減少無(wú)用計(jì)算來(lái)節(jié)約計(jì)算資源,所以通常來(lái)說(shuō)這并不是一個(gè)太大的問(wèn)題,它只會(huì)白白消耗計(jì)算資源,并不會(huì)造成錯(cuò)誤。而且如果你需要的話,你也可以比較容易地在提供這個(gè) Promise 的地方實(shí)現(xiàn)。
