0%

JS核心-(73)-Promise-創立自己的 Promise

前言

如何建立自己的 Promise

建立 Promise

首先我們先來看看 Promise 的建構函式

console.log(Promise);

檢查了以後發現什麼都看不到,這個時候就要用 console.dir 針對 Promise 進行檢查

console.dir(Promise);

之後你可以看到,如果將 Promise 實體化 (new Promise),他可以用的方法就是紅色框框框起來的這些。

那麼 Promise 本身作為物件,被插入的方法就是藍色框框的這些方法:例如上一篇文章介紹到的 Promise.all();

那我們一樣試著將 Promise 實體化看看:

const a = new Promise();

console.log(a);

為什麼會跳錯呢?其實是因為在將 Promise 實體化的時候,同時必須傳入一個 callbackfunction 才行。

const a = new Promise(() => {

});

console.log(a);

之後你就會發現,原來這個 Promisepending 的狀態,因為我們還沒有設定,怎樣的狀況是

resolve ,怎樣的狀況是 reject

所以首先我們得先傳入 resolve 以及 reject 的參數,並且同時只能回傳其中一種狀態。

const a = new Promise((resolve, reject) => {
    resolve('成功');
});

console.log(a);

可以看到,如果我們直接執行 resolve 的語法的話,Promise 的狀態就從 pending 改為 resolved

如果我們要取得 resolve 所傳入的參數,就要使用 then 的語法去承接

const a = new Promise((resolve, reject) => {
    resolve('成功');
});

console.log(a);
a
    .then((res) => {
        console.log(res);
    });


那麼今天如果是失敗的 reject 的話呢?

const a = new Promise((resolve, reject) => {
    reject('失敗');
});

console.log(a);
a
    .then((res) => {
        console.log(res);
    });

因為我們沒有使用 .catch 去承接失敗,所以這邊他就提示 Uncaught 的狀態。

const a = new Promise((resolve, reject) => {
    reject('失敗');
});

a
    .then((res) => {
        console.log(res);
    })
    .catch((err) => {
        console.log(err);
    });

這樣就完美接到失敗的訊息了。

另外其中的 res 以及 err 都是自訂的參數名稱,你要取什麼名字都可以,以上就是實際上 Promise 的實際操作概念,但是實

務上我們不太會這樣使用。原因在於,a 說到底也只是個物件而已,如果我們有其他的參數要進行判斷、計算、調整,只用物

件是沒有辦法的,必需使用一個函式,回傳這個 Promise 的物件,這樣就可以同時傳入參數進行處理,又可以進行 Promise

定義。

關於這個函式,不論你是要使用函式陳述式還是函式表達式都是可以的,範例這邊就先使用函式陳述式來進行開始

// 定義
function promiseFn (num) {
    return new Promise( (resolve, reject) => {
        setTimeout(() => {
            if (num) {
                resolve('成功');
            } else {
                reject('失敗');
            }
        }, 10);
    });
}

// 執行
promiseFn(1)
    .then((res) => {
        console.log(res);
    })
    .catch((err) => {
        console.log(err);
    });

console.log('Code End');

利用 num 的參數判斷是真值還是假值,進而執行 resolve 還是 reject,執行的時候再用 then 以及 catch 分別接收成功以

及失敗的結果。只是最後不同的地方在於,我這邊多加了一個 Code End,大家想看看,這樣執行的順序是什麼呢?是結果會先

出來,還是 Code End 會先出來?

答案是 Code End 出來,因為 setTimeout 就是非同步,所以今天就算執行延遲毫秒改成 0 ,結果也還是一樣。

那麼執行順序會是怎麼樣呢?

// 定義
function promiseFn (num) {
    console.log(1);
    return new Promise( (resolve, reject) => {
        console.log(2);
        setTimeout(() => {
            if (num) {
                resolve('成功');
            } else {
                reject('失敗');
            }
        }, 10);
    });
}

// 執行
promiseFn(1)
    .then((res) => {
        console.log(res);
    })
    .catch((err) => {
        console.log(err);
    });

console.log('Code End');

這邊加上了 12 ,也就是說在執行完 2 之後,就先把 setTimeout 放到事件佇列中,再繼續執行 Code End

之後才來執行 setTimeout 的內容。