從外部改變promise內部狀態
promise是什麼?
1、主要用於非同步計算
2、可以將非同步操作佇列化,按照期望的順序執行,返回符合預期的結果
3、可以在物件之間傳遞和操作promise,幫助我們處理佇列
為什麼會有promise?
為了避免介面凍結(任務)
-
同步:假設你去了一家飯店,找個位置,叫來服務員,這個時候服務員對你說,對不起我是“同步”服務員,我要服務完這張桌子才能招呼你。那桌客人明明已經吃上了,你只是想要個選單,這麼小的動作,服務員卻要你等到別人的一個大動作完成之後,才能再來招呼你,這個便是同步的問題:也就是“順序交付的工作1234,必須按照1234的順序完成”。
-
非同步:則是將耗時很長的A交付的工作交給系統之後,就去繼續做B交付的工作,。等到系統完成了前面的工作之後,再通過回撥或者事件,繼續做A剩下的工作。
AB工作的完成順序,和交付他們的時間順序無關,所以叫“非同步”。
而官方文件則表示
Promise 物件的狀態不受外界影響。Promise 物件代表一個非同步操作,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和 Rejected(已失敗)。只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。這也是 Promise 這個名字的由來,它的英語意思就是「承諾」,表示其他手段無法改變。
但是經過實際測試從外部控制promise狀態的事其實是可以辦到的:
1、Promise的狀態取決於promise主體中是否呼叫了resolved或者reject或者在呼叫resolved和reject前就發生異常(將會直接進入 reject狀態)
2、Promise也是js物件(雖然它實際是個函式)、逃不開按地址引用帶來的副作用,呼叫reject,但是沒有設定fn的reject,或者catch,故會報錯。Promise允許不設定resolved方法(即如果直接呼叫obj.ok()是沒問題的,不會報錯,promise狀態也會變為resolved)、但如果出現異常或者主動呼叫進入reject而沒有設定reject方法 或catch方法,則會報錯。
具體實現程式碼demo
let obj = {} // 用於儲存promise裡的resolve和reject方法 let a = function(){ let p = new Promise(function(resolve,reject){ obj.ok = resolve; obj.cancel = reject; }); return p; } async function test () { // 使用async/await測試效果 console.log('test開始') let c = await a(); console.log(c) console.log('test結束'); } test() setTimeout(function(){ obj.ok('哈哈哈哈哈') },2000)
結果為
試驗證明在promise外部通過地址引用的方式進行改變promise內部狀態是可以實現的。
思路來源於
https://segmentfault.com/u/joey_5a961933efd3e
這位老哥在
https://segmentfault.com/q/1010000011145129
這篇博文裡的評論。