ES6—Promise詳解

目錄

一、概述

二、詳解

三、拓展


一、概述

Promise是異步編程的一種解決方案,提供了統一的API,可以用同樣的方法處理各種異步操作。Promise類似一個容器,裏面保存着一個異步操作的結果。

Promise是ES6內置的一個構造函數,用來創建Promise實例,處理異步操作。Promise構造函數接收一個函數作爲參數,作爲參數的函數有兩個參數,這兩個參數均是JS內置函數,一般命名爲resolve和reject。注意,Promise實例創建後立即執行。

new Promise((resolve, reject) => {

});

二、詳解

知識點1:Promise實例狀態

Promise實例有三個狀態,分別是pending進行中、resolved已成功、rejected已失敗。

Promise實例狀態的變化有兩種情況,其一從pending變爲resolved,只能由resolve函數觸發,其二從pending變爲rejected,發生異常時觸發。實例狀態一旦改變,狀態即被固化,不會發生二次變化,任何時刻給Promise實例添加對應狀態的回調函數,都可以獲取實例的狀態結果。

new Promise((resolve) => {
    resolve(); // 狀態變爲resolved
    reject();  // 無效, 實例狀態已變爲resolved, 固化不能修改
});

注意,狀態變化是同步操作,在第一輪事件循環中執行。Promise實例狀態變化後,回調函數在本輪事件循環的末尾執行,總是晚於本輪循環的同步任務,即第一輪事件循環的末尾會檢測Promise實例狀態,決定是否立即調用回調函數。

new Promise((resolve) => {
    resolve(); // 同步操作、狀態變爲resolved
}).then(() => {
    // 檢測到Promise實例狀態變爲resolved
    // 則第一輪事件循環末尾執行,即同步操作執行完立即執行
})

Promise實例狀態變爲resolved或rejected,代表當前Promise實例的使命已完成,後續如果還有操作,實際上是沒有意義的,可以利用return語句避免這種情況。

new Promise((resolve) => {
    return resolve(1);
    console.log(2); // 不會執行, 若去掉return, 會執行, 但沒有意義
})

知識點2:內置函數resolve

異步操作成功時調用resolve函數,可以將Promise實例的狀態從pending修改爲resolved,並在本輪循環的末尾執行成功回調函數。本輪循環的末尾即同步操作執行完成後立即執行的意思。注意,resolve函數是將Promise實例狀態從pending變爲resolved的唯一方法。

如下代碼所示,有兩輪事件循環。第一輪事件循環執行同步操作:創建Promise實例、打印1、執行resolve將實例狀態變爲resolved、打印2。因爲實例狀態變爲resolved,所以第一輪事件循環末尾執行成功回調函數,打印3。第二輪事件循環執行異步操作:執行定時器,打印4。

new Promise((resolve) => {
    setTimeout(() => {
        console.log(4);
    });
    console.log(1);
    resolve();
    console.log(2);
}).then(() => {
    console.log(3);
});

// 打印順序:1 2 3 4

resolve函數可以設置一個參數,該參數可被傳遞給成功回調函數。

new Promise((resolve) => {
    resolve(1);
}).then((res) => {
    console.log(res); // 1
});

resolve函數的參數可以是正常值,也可以是另一個Promise實例。調用resolve並不會終結作爲其參數的Promise實例的執行。

如果resolve的參數是一個Promise實例,則執行該resolve語句並不會改變當前Promise實例的狀態,其狀態由作爲參數的Promise實例的狀態決定,且作爲參數的Promise實例的返回值就是當前實例的返回值。

const p1 = new Promise((resolve, reject) => {
    setTimeout(reject, 2000, 1);
    // 如果改爲setTimeout(resolve, 2000, 1), 則最後打印"正確1"
});

const p2 = new Promise((resolve) => {
    resolve(p1);
});

p2.then((res) => {
    console.log(`正確${res}`);
}).catch((err) => {
    console.log(`錯誤${err}`);
});

// 打印:錯誤1

// p1的狀態決定了p2的狀態。 
// 如果p1狀態爲pending, p2的回調函數會等到p1的狀態改變時才觸發
// 如果p1狀態爲resolved, p2狀態爲resolved
// 如果p1狀態爲rejected, p2狀態爲rejected

如下代碼所示,第一輪事件循環:創建實例p1、執行reject將p1的狀態變爲rejected、 創建p2。第二輪事件循環:執行定時器,5s後執行resolve,p2獲取p1的狀態,爲resolved,觸發p2的失敗回調函數打印1。

const p1 = new Promise((resolve, reject) => {
    reject(1);
});
const p2 = new Promise((resolve) => {
    setTimeout(() => {
        resolve(p1);
    }, 5000); 
});
p2.catch((err) => {
    console.log(err); // 5s後打印1
});

 知識點3:內置函數reject

異步操作失敗時調用reject函數,可以將Promise實例的狀態從pending修改爲rejected,並在本輪循環的末尾執行失敗回調函數。本輪循環的末尾即同步操作執行完成後立即執行的意思。

如下代碼所示,有兩輪事件循環。第一輪事件循環執行同步操作:創建Promise實例、執行reject將實例狀態變爲rejected、打印1。因爲實例狀態變爲rejected,所以第一輪循環末尾執行失敗回調函數,打印2。第二輪事件循環執行異步操作:執行定時器,打印3。

new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log(3);
    });
    reject(2);
    console.log(1);
}).catch((res) => {
    console.log(res);
});

// 1 2 3

與resolve函數不同,reject函數不是將Promise實例狀態從pending變爲rejected的唯一方法。reject函數的作用是拋出異常,即只要Promise實例拋出異常,就可以改變狀態,例如如下代碼。

new Promise(() => {
    throw 1; // 拋出異常
    // throw new Error('自定義的錯誤');
}).catch((res) => {
    console.log(res); // 1
});
new Promise(() => {
    console.log(null.split()); // 拋出異常
}).catch((res) => {
    console.log(res); // TypeError: Cannot read property 'split' of null
});

 注意,如下代碼所示,定時器內部出現的異常,並不是Promise實例內部的異常,所以沒有被catch捕獲。

new Promise(() => {
    setTimeout(() => {
        console.log(null.split()); // 拋出異常
    });
}).catch(() => {
    console.log(1); // 不執行
});

知識點4:Promise實例的缺點

其一:一旦創建會立即執行,無法中途取消

其二:如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部(信息會打印到控制檯,不會終止外部腳本執行)

其二:實例狀態爲pending時,無法知道目前具體進展到哪一步,是剛開始還是即將結束

知識點5:Promise.prototype.then()

then方法定義在Promise構造函數的原型上,用來設置Promise實例的回調函數。

then方法接收兩個參數。第一個參數必填,設置異步操作成功的回調函數。第二個參數選填,設置異步操作失敗的回調函數。不推薦使用第二個參數,因爲第二個參數設置的失敗回調函數無法監聽第一個參數設置的成功回調函數。推薦使用catch方法設置失敗回調函數,因爲catch亦可以捕獲前面then方法執行中的錯誤。

// 不推薦
promise.then(() => {
    // 成功的回調
}, () => {
    // 失敗的回調
});
// 推薦
promise.then((() => {
    // 成功的回調
}).catch(() => {
    // 失敗的回調
});

then方法返回的結果是一個新的Promise實例,實例狀態爲resolved或rejected。當成功回調函數執行完內部的所有同步任務,若沒有異常,則狀態爲resolved,否則爲rejected。異步操作不影響實例狀態。

new Promise((resolve) => {
    resolve();
}).then(() => {

}).then(() => {

}).then(() => {

});

// 因爲then方法返回的結果是新的Promise實例,所以可以採用鏈式結構,連接多個then方法

如下代碼所示,第一輪事件循環執行同步任務:因爲Promise實例創建後立即執行,所以先執行resolve,實例狀態變爲resolved、打印1、打印2。第一輪事件循環末尾檢測到instance1實例的狀態變爲resolved,所以執行其成功回調函數,打印3。instance2實例內部的同步任務執行完後,沒有任何異常,所以instance2實例的狀態變爲resolved,instance2同步操作的末尾檢測到其實例狀態爲resolved,所以立即觸發其成功回調函數:打印4。最後執行第二輪事件循環即異步操作:第一個定時器從此時開始,3s後執行,第二個定時立即執行,所以先打印5,再打印6。

const instance1 = new Promise((resolve) => {
    resolve();
    console.log(1);
    setTimeout(() => {
       console.log(6);
    }, 3000);
});

const instance2 = instance1.then(() => {
    setTimeout(() => {
        console.log(5);
    }, 5000);
    console.log(3);
});

instance2.then(() => {
    console.log(4);
});

console.log(2);

// 1 2 3 4 5 6

如下代碼所示,第一輪事件循環執行同步任務:因爲Promise實例創建後立即執行,所以先執行resolve,Promise實例狀態變爲resolved。第一輪事件循環末尾檢測到Promise實例的狀態變爲resolved,所以觸發第一個then設置的成功回調函數。因爲第一個then設置的成功回調函數內的同步任務沒有發現異常,所以執行完其同步任務後,第一個then返回的Promise實例狀態變爲resolved,隨機立即觸發第二個then設置的成功回調函數,打印2。第二輪事件循環執行異步操作:執行定時器,從此時開始3s後,打印1。

new Promise((resolve) => {
    resolve();
}).then(() => {
    setTimeout(() => {
        console.log(1)
    }, 3000);
}).then(() => {
    console.log(2)
});

// 2
// 1

如下代碼所示,then方法設置的成功回調函數內可使用return語句給下一個then方法設置的成功回調函數傳值。

new Promise((resolve) => {
    resolve(); // 觸發第一個then設置的成功回調函數(這是唯一方法)
}).then(() => {
    return 1;
}).then((res) => {
    console.log(res); // 1
});

多個then方法採用鏈式結構,若前一個成功回調函數return一個Promise實例,則後一個成功回調函數會在該實例狀態變爲resolved後,再被調用。

Promise.resolve(1).then((res) => {
    return new Promise((resolve) => {
        setTimeout(resolve, 2000, res);
    });
}).then((data) => {
    console.log(data);
});

知識點6:Promise.prototype.catch()

catch方法定義在Promise構造函數的原型上,接收一個參數,用來設置Promise實例的失敗回調函數。

new Promise((resolve, reject) => { reject() }).then(null, () => { }); // 不推薦

// 等同於
new Promise((resolve, reject) => { reject() }).then(undefined, () => { }); // 不推薦

// 等同於
new Promise((resolve, reject) => { reject() }).catch(() => { }); // 推薦
const fn = new Promise(function (resolve) {
    resolve(1);
});

fn.then(() => {
    // ......
}).catch((err) => {
    console.log(err);
});

// 如果fn的狀態變爲resolved, 則調用then指定的成功回調函數
// 如果fn的狀態變爲rejected, 則調用catch指定的失敗回調函數
// 如果then中成功回調函數運行過程中拋出錯誤, 也會被catch方法捕獲

catch同then方法一樣,返回的結果也是一個新的Promise實例,也可以採用鏈式結構,原理同then一致。

Promise.resolve().then(() => {
    // ...
}).catch(() => {
    // ...
}).catch(() => {
    // ...
});

Promise實例的異常具有冒泡性質,會一直向後傳遞,直到被捕獲爲止,即錯誤總會被下一個catch語句捕獲。

new Promise(() => {
    console.log(null.split());
}).then(() => {
    console.log(1);   // 不執行
}).then(() => {
    console.log(2);   // 不執行
}).catch((err) => {
    console.log(err); // TypeError: Cannot read property 'split' of null
});

Promise實例如果沒有設置失敗回調函數,則其出現的異常不會傳遞到外層代碼,不會終止腳本執行,即Promise內部的錯誤不會影響到Promise外部代碼的執行。

如下代碼所示,第一輪事件循環執行同步任務:創建Promise、打印1。第一輪事件循環末尾打印Promise內部的異常信息。第二輪事件循環執行異步操作:打印2。

new Promise(() => {
    setTimeout(() => {
        console.log(2);
    });
    console.log(null.split());
});

console.log(1);

// 1
// TypeError: Cannot read property 'split' of null
// 2

知識點7:Promise.prototype.finally()

finally方法定義在Promise構造函數的原型上,用來設置一個回調函數,不管實例狀態最後是resolved還是rejected,該回調函數都會執行。

new Promise((resolve) => { }).then(() => { }).catch(() => { }).finally(() => {

});

finally方法返回的結果和then方法一樣,也是一個新的Promise實例,原理相同。

const promise = new Promise((resolve) => {
    resolve();
}).finally(() => {
    console.log(2);
});
console.log(promise);

// Promise
// 2

finally方法設置的回調函數不接受任何參數,所以無法知道Promise實例的狀態究竟是resolved還是rejected,所以finally方法裏的操作,與狀態無關,不依賴於Promise實例的執行結果。

三、拓展

拓展1:Promise.all()

該方法可以將多個Promise實例,封裝成一個新的Promise實例。它接受一個數組作爲參數,數組元素一般皆爲Promise實例,如果不是,則優先調用Promise.resolve方法將其轉換爲Promise實例。注意,Promise.all方法的參數也可以不是數組,但必須具有Iterator接口,且返回的每個成員都是Promise實例。

const promise = Promise.all([p1, p2, p3]);

Promise.all方法返回的封裝實例的狀態由參數中各個元素實例的狀態決定。只有元素實例的狀態都爲resolved,封裝實例的狀態纔會變爲resolved,此時元素實例的返回值組成一個數組,作爲參數傳遞給封裝實例的成功回調函數。

const p1 = new Promise((resolve) => {
    resolve(1);
});
const p2 = new Promise((resolve) => {
    resolve(2);
});
const p3 = new Promise((resolve) => {
    resolve(3);
});
Promise.all([p1, p2, p3]).then((res) => {
    console.log(res); // [1, 2, 3]
});

只要有一個元素實例的狀態變爲rejected,封裝實例的狀態就會變爲rejected(不影響其它腳本執行),此時第一個狀態變爲rejected的元素實例的返回值會作爲參數,傳遞給封裝實例的失敗回調函數。

創建封裝實例時,會根據元素實例的狀態來設置封裝實例的狀態。

在第一輪事件循環中,如果有元素實例的狀態變爲rejected,則封裝實例初創時狀態爲rejected,第一輪事件循環末尾執行封裝實例的失敗回調函數。

在第一輪事件循環中,如果所有元素實例的狀態都變爲了resolved,則封裝實例初創時狀態爲resolved,第一輪事件循環末尾執行封裝實例的成功回調函數。

在第一輪事件循環中,如果沒有元素實例的狀態變爲rejected,且有的狀態爲pending,則第一輪事件循環末尾不執行封裝實例的回調函數。第二輪事件循環中,有元素實例的狀態變爲rejected或所有元素實例狀態都變爲resolved的那一刻,則封裝實例的狀態立即變爲rejected,並立即觸發相應的回調函數(不用等到第二輪事件循環末尾在執行回調函數)。

如下代碼所示,第一輪事件循環:創建Promise實例p1、p2、p3、p4、打印p4、打印1。第二輪事件循環:執行定時器,打印p1、p2,執行reject將p2的狀態變爲rejected、p4的狀態也隨之立即變爲rejected,並立即觸發p4的失敗回調函數打印2、之後繼續執行定時器,打印p3、p4。

const p1 = new Promise((resolve) => {
    setTimeout(() => {
        console.log('p1');
        resolve(1);
    });
});
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('p2');
        reject(2);
    });
});
const p3 = new Promise((resolve) => {
    setTimeout(() => {
        console.log('p3');
        resolve(3);
    });
});
const p4 = Promise.all([p1, p2, p3]);

p4.catch((e) => {
    console.log(e);
    setTimeout(() => {
        console.log('p4');
    });
});

console.log(p4);
console.log('1');

// Promise
// 1
// p1
// p2
// 2
// p3
// p4

如下代碼所示,第一輪事件循環:創建Promise實例p1、創建p2並執行reject將p2狀態變爲rejected、創建p3、創建p4(p4同p2狀態一樣爲rejected)、打印p4、打印1。第一輪事件循環末尾檢測到p4狀態爲rejected,所以觸發p4的失敗回調函數,打印2。第二輪事件循環:執行定時器,打印p1、p2、p3、p4。

const p1 = new Promise((resolve) => {
    setTimeout(() => {
        console.log('p1');
        resolve(1);
    });
});
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('p2');
    });
    reject(2);
});
const p3 = new Promise((resolve) => {
    setTimeout(() => {
        console.log('p3');
        resolve(3);
    });
});
const p4 = Promise.all([p1, p2, p3]);

p4.catch((e) => {
    console.log(e);
    setTimeout(() => {
        console.log('p4');
    });
});

console.log(p4);
console.log('1');

// Promise
// 1
// 2
// p1
// p2
// p3
// p4

如下代碼所示,p1指向then方法返回的新Promise實例,狀態爲resolved。p2指向catch方法返回的新Promise實例,狀態爲resolved。因此封裝實例的狀態爲resolved,在第一輪事件循環的末尾觸發成功回調函數。

const p1 = new Promise((resolve) => {
    resolve('p1');
}).then((res) => {
    return res;
});

const p2 = new Promise((resolve, reject) => {
    reject('p2');
}).catch((res) => {
    return res;
});

Promise.all([p1, p2]).then((res) => {
    console.log(res)
});

// ["p1", "p2"]

拓展2:Promise.race()

該方法可以將多個Promise實例,封裝成一個新的Promise實例,它接受一個數組作爲參數,數組元素一般皆爲Promise實例,如果不是,則優先調用Promise.resolve方法將其轉換爲Promise實例。

const promise = Promise.race([p1, p2, p3]);

只要任意一個元素實例率先改變狀態,Promise.race方法返回的封裝實例的狀態就會隨之改變,該元素實例的返回值會傳遞給封裝實例的回調函數。

創建封裝實例時,會根據元素實例的狀態來設置封裝實例的狀態。

在第一輪事件循環中,如果有元素實例的狀態率先變爲rejected,則封裝實例初創時狀態爲rejected,第一輪事件循環末尾執行封裝實例的失敗回調函數。

在第一輪事件循環中,如果有元素實例的狀態率先變爲resolved,則封裝實例初創時狀態爲resolved,第一輪事件循環末尾執行封裝實例的成功回調函數。

在第一輪事件循環中,如果沒有元素實例的狀態變化,則第一輪事件循環末尾不執行封裝實例的回調函數。第二輪事件循環中,有元素實例的狀態率先發生變化,則封裝實例的狀態立即隨之變化,並立即觸發相應的回調函數(不用等到第二輪事件循環末尾在執行回調函數)。

如下代碼所示,第一輪事件循環:創建實例p1、執行resolve將p1狀態變爲resolved、打印p1、創建實例p2、執行reject將p2狀態變爲rejected、創建實例p3,因爲p1狀態率先改變,所以p3的狀態爲resolved、打印實例p3。第一輪事件循環末尾檢測到p3實例狀態爲resolved,所以觸發其成功回調函數,打印1。第二輪事件循環:執行定時器,打印p2。

const p1 = new Promise((resolve) => {
    resolve(1);
    console.log('p1');
});
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('p2');
    });
    reject(2);
});

const p3 = Promise.race([p1, p2]);
p3.then((res) => {
    console.log(res);
}).catch((err) => {
    console.log(err);
});
console.log(p3);

// p1
// Promise [[PromiseStatus]]: "resolved", [[PromiseValue]]: 1
// 1
// p2

如下代碼所示,第一輪事件循環:創建實例p1、創建實例p2、創建實例p3、打印1。第一輪事件循環末尾沒有檢測到任何實例狀態發生變化,所以不執行回調函數。第二輪事件循環:執行定時器,首先執行resolve將p1的狀態變爲resolved(則封裝實例p3的狀態也隨之變化,並立即觸發其成功回調函數,打印2)、打印p1、打印p2、執行reject將p2狀態變爲rejected。

const p1 = new Promise((resolve) => {
    setTimeout(() => {
        resolve(2);
        console.log('p1');
    });
});

const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('p2');
        reject(3);
    });
});

const p3 = Promise.race([p1, p2]);
p3.then((res) => {
    console.log(res);
}).catch((err) => {
    console.log(err);
});

console.log(1);

// 1
// p1
// 2
// p2

拓展3:Promise.allSettled() 

該方法可以將多個Promise實例,封裝成一個新的Promise實例,它接受一個數組作爲參數,數組元素一般皆爲Promise實例,如果不是,則優先調用Promise.resolve方法將其轉換爲Promise實例。只有等到所有元素實例都返回結果,不管是resolved還是rejected,封裝實例的狀態纔會變化,且其狀態只能是resolved。

Promise.allSettled([1, 2]).then((res) => {
    console.log(res);
});

// [ {status: "fulfilled", value: 1}, {status: "fulfilled", value: 2} ]

如下代碼所示,第一輪事件循環:創建實例p1、p2、p3、打印實例p3、打印1。第二輪事件循環:執行定時器,打印p1、執行resolve將p1的狀態變爲resolved、打印p2、執行reject將p2的狀態變爲rejected、打印2(本定時器內同步任務執行完成後,檢測到兩個元素實例的狀態均已改變,所以封裝實例的狀態變爲resolved,觸發成功回調函數,打印數組)、執行下一個定時器,打印3。

const p1 = new Promise((resolve) => {
    setTimeout(() => {
        console.log('p1');
        resolve(2);
    });
});

const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('p2');
        reject(3);
        console.log(2);
        setTimeout(() => {
            console.log(3);
        });
    });
});

const p3 = Promise.allSettled([p1, p2]).then((res) => {
    console.log(res);
});

console.log(p3);
console.log(1);

// Promise
// 1
// p1
// p2
// 2
// [ {status: "fulfilled", value: 2}, {status: "rejected", reason: 3} ]
// 3

封裝實例的成功回調函數接受一個數組作爲參數,每個數組元素對應一個構成封裝實例的元素實例。

如下代碼所示,封裝實例的成功回調函數接受一個數組作爲參數,每個數組元素都有status屬性,屬性值爲字符串fulfilled或字符串rejected,fulfilled時,對象有value屬性,rejected時,對象有reason屬性,對應兩種狀態的返回值。

const p1 = Promise.resolve(42);
const p2 = Promise.reject(-1);

const p3 = Promise.allSettled([resolved, rejected]);

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

// [
//    { status: 'fulfilled', value: 42 },
//    { status: 'rejected', reason: -1 }
// ]

如果不關心異步操作的結果,只在乎操作是否結束,那麼Promise.allSettled方法非常好用,否則想要確保所有操作都結束非常麻煩。

拓展4:Promise.resolve()

該方法可以將現有對象轉換爲一個新的Promise實例,狀態根據參數而定。

const promise = Promise.resolve(1);
// 等價於
new Promise((resolve) => {
    resolve(1)
});

Promise.resolved方法的參數有四種情況。

如果Promise.resolve的參數是一個Promise實例,將不做任何改變,直接返回這個實例。

如果Promise.resolve的參數是一個thenable對象,將把該對象轉化爲Promise實例,並立即執行其then方法。thenable對象是指具有then方法的對象,如下代碼所示。

let thenable = {
    then: (resolve) => {
        resolve(42);
    }
};

 then方法決定生成的Promise實例的狀態。

let thenable = {
    then: () => {
        console.log(1);
    }
};

const p = Promise.resolve(thenable);

p.then(() => {
    console.log(2);
});

console.log(p);

// Promise [[PromiseStatus]]: "pending" [[PromiseValue]]: undefined
// 1
let thenable = {
    then: (resolve) => {
        console.log(1);
        resolve();
        console.log(2);
    }
};

const p = Promise.resolve(thenable);

p.then(() => {
    console.log(3);
});

console.log(p);

// Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: undefined
// 1
// 2
// 3
let thenable = {
    then: (resolve, reject) => {
        console.log(1);
        reject();
        console.log(2);
    }
};

const p = Promise.resolve(thenable);

p.catch(() => {
    console.log(3);
});

console.log(p);

// Promise [[PromiseStatus]]: "rejected" [[PromiseValue]]: undefined
// 1
// 2
// 3

如果Promise.resolve的參數是一個原始值或一個不具有then方法的對象,該方法將返回一個新的Promise實例,狀態爲resolved。Promise.resolve的參數會直接傳遞給成功回調函數。

const p1 = Promise.resolve(1);

p1.then((res) => {
    console.log(res); // 1
});

如果Promise.resolve不帶任何參數,將直接返回一個新的Promise實例,狀態爲resolved。如果想得到一個Promise實例,比較簡單的方法是直接調用Promise.resolve方法。

const promise = Promise.resolve();

promise.then((res) => {
    console.log(res); // undefined
});

拓展5:Promise.reject() 

該方法可以將現有對象轉化爲一個新的Promise實例,實例狀態爲rejected。Promise.reject方法的參數會直接傳遞給失敗回調函數。

const promise = Promise.reject(1);
// 等同於:const promise = new Promise((resolve, reject) => reject(1))

promise.catch((err) => {
    console.log(err); // 1
});
const promise = Promise.reject();

promise.catch((err) => {
    console.log(err); // undefined
});
const thenable = {
    then(resolve, reject) {
        reject(1);
    }
};

Promise.reject(thenable).catch((err) => {
    console.log(err === thenable); // true
});

// Promise.reject方法的參數是一個thenable對象
// catch方法的參數不是1, 而是這個thenable對象

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章