源碼網址:
https://github.com/YvetteLau/Blog/issues/2
Promise建構子函數
Property
status
Promise的狀態,初始為'pending'
非同步操作成功後為'fulfilled'
,失敗為'rejected'
resolve
成功後調用的函數
接收一個參數value,
把status
改為'fulfilled'
reject
失敗後調用的函數
接收一個參數value,定義為Promise的property
把status
改為'rejected'
onFulfilled
為一陣列,元素是函數
放進等待執行的回調函數(成功)
onRejected
為一陣列,元素是函數
放進等待執行的回調函數(失敗)
Promise.prototype.then
定義
接收兩個參數,皆為函數,一個成功時的回調(onFulfilled
),一個失敗時的回調(onRejected
)
返回一個Promise(範例變數叫promise2
)
Promise的非同步操作是,先判定status的狀態
當status === FULFILLED
呼叫成功時的回調函數,引入value當參數,return value賦值給x
然後執行resolvePromise(promise2, x, resolve, reject)
當status ===``REJECTED
呼叫成功時的回調函數,引入reason當參數,return reason賦值給x
然後執行resolvePromise(promise2, x, resolve, reject)
當status === PENDING
propertyonFulfilled
陣列push進一個非同步操作
為上面第一點內容
propertyonRejected
陣列push進一個非同步操作
為上面第二點內容
🔎 註一
程式碼剛開始執行時,由於非同步函數還沒開始,Promise狀態是pending,所以一定都是先跑到3,想不太到跑到1、2的情況
resolvePromise
定義
如同函數名,旨在處理成功時的回調(onFulfilled
)所回傳的Promise
resolvePromise(promise2, x, resolve, reject)
接收四個參數,分別為
- then()返回的Promise
- 成功or失敗回調函數的回傳值
- 1的Promise resolve
- 1的Promise reject
先判斷promise2 === x
為真的話,執行reject(new TypeError('Chaining cycle'))
後面之後再補看
先引用來源的說明
簡單來說要處理Promise chain的產生

模擬執行順序測試
測試1

a.then
是同步的,在非同步操作之前,過1000ms後,123出現
測試2
在then定義裡面,在實現、拒絕、擱置三種情況的區塊裡面,加入console.log,看看程式碼執行時怎麼跑的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; function Prom(executor) { let self = this; self.status = PENDING; self.onFulfilled = []; self.onRejected = []; function resolve(value) { if (self.status === PENDING) { self.status = FULFILLED; self.value = value; self.onFulfilled.forEach(fn => fn()); } }
function reject(reason) { if (self.status === PENDING) { self.status = REJECTED; self.reason = reason; self.onRejected.forEach(fn => fn()); } }
try { executor(resolve, reject); } catch (e) { reject(e); } }
Prom.prototype.then = function (onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }; let self = this; let promise2 = new Prom((resolve, reject) => { if (self.status === FULFILLED) { console.log('then裡面 FULFILLED') setTimeout(() => { try { let x = onFulfilled(self.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } else if (self.status === REJECTED) { console.log('then裡面 REJECTED') setTimeout(() => { try { let x = onRejected(self.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } else if (self.status === PENDING) { console.log('then裡面 PENDING') self.onFulfilled.push(() => { setTimeout(() => { try { let x = onFulfilled(self.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); }); self.onRejected.push(() => { setTimeout(() => { try { let x = onRejected(self.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); }); } }); return promise2; }
function resolvePromise(promise2, x, resolve, reject) { let self = this; if (promise2 === x) { reject(new TypeError('Chaining cycle')); } if (x && typeof x === 'object' || typeof x === 'function') { let used; try { let then = x.then; if (typeof then === 'function') { then.call(x, (y) => { if (used) return; used = true; resolvePromise(promise2, y, resolve, reject); }, (r) => { if (used) return; used = true; reject(r); });
}else{ if (used) return; used = true; resolve(x); } } catch (e) { if (used) return; used = true; reject(e); } } else { resolve(x); } }
let P1 = new Prom((a, b) => { setTimeout(() => { a('123') }, 1000) })
P1.then((value) => { console.log(value) return '安安' }) .then((value) => { console.log(value) })
|
以下為output
1 2 3 4
| then裡面 PENDING <----同步階段 then裡面 PENDING <----同步階段 123 <----非同步階段 安安 <----非同步階段
|
此為註一的測試,目前想知道甚麼情況會跑到FULFILLED和REJECTED區塊
改成這樣的話
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let P1 = new Prom((a, b) => { setTimeout(() => { a('123') }, 1000) })
P1.then((value) => { console.log(value) let P2 = new Prom((a, b) => { setTimeout(() => { a('465') }, 1000) }) return P2 }) .then((value) => { console.log(value) })
|
第一個then改成回傳Promise
output:
1 2 3 4 5
| then裡面 PENDING then裡面 PENDING 123 then裡面 PENDING 465
|