2. 實作你自己的 MyPromise
下面的 sleep() 用的不是原生 Promise,而是自己實作的 MyPromise。呼叫端維持原樣,await、then、catch 都要能用。
function sleep(sec) {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(sec);
}, sec * 1000);
});
}
await sleep(2);
sleep(2).then(funcThen).catch(funcCatch);
下面是一份寫到一半的草稿,請把它補完。
class MyPromise {
constructor(func) {
let resolve = (val) => {
this.resolverFunc && this.resolverFunc(val)
}
function reject(err) {
throw new Error(err);
}
func(resolve, reject);
}
then(func1) {
this.state = 'resolved';
this.resolverFunc = func1;
}
catch(func2) {
}
}
驗收標準
await myPromise要能運作,resolve(val)帶的值即為await的結果。then(onFulfilled)的回呼要拿到resolve(val)帶的值。- executor 同步呼叫
resolve()時,之後才註冊的then()回呼仍然要被執行。 then()可以鏈式串接,前一個回呼的回傳值傳給下一個;若回傳的是 thenable,要等它 settle 之後才往下走。catch()要接得到reject(err),也要接得到 executor 裡同步throw的錯誤。- 一個 promise 只能 settle 一次,之後再呼叫
resolve/reject都無效。 - 回呼一律非同步執行,不可以在
resolve()當下同步呼叫。 - 同一個 promise 上註冊多個
then(),每個都要被通知。
測試
右邊編輯器附了四段測試。A 段可以直接執行,B、C、D 預設註解起來,完成後四段都要能通過。
預期輸出
+ 0ms C: caught boom + 0ms D: sync + 1000ms A: awaited 1s + 3000ms B: total 3s
按「執行」開始,輸出會標示相對時間,方便確認真的等了 2 秒。