語法糖
catch 其實是 then(undefined, () => {}) 的語法糖,如下:
let p = Promise.reject("error");
// catch
p.catch(err => {
console.log("catch " + err); // catch error
});
// then
p.then(undefined, err => {
console.log("catch " + err); // catch error
});
捕獲錯誤
Promise對象內(nèi)部其實自帶了try catch,當同步代碼發(fā)生運行時錯誤時,會自動將錯誤對象作為值reject灸叼,這樣就會觸發(fā)catch注冊的回調(diào),如下:
let p = new Promise((resolve, reject) => {
throw "error";
});
p.catch(err => {
console.log("catch " + err); // catch error
});
但需要注意的是:
- 異步代碼的運行時錯誤無法被自動 reject 進而被 catch 捕獲,而是直接報錯:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
throw "error";
}, 0);
});
p.catch(err => {
console.log("catch " + err); // 不會被執(zhí)行
});
關于異步錯誤是否會被 catch 捕獲其實還有點坑蜜另,事實證明之所以 setTimeout 中產(chǎn)生的錯誤不會被 catch 捕獲到,原因是 js 的事件隊列中愁茁,Promise 的 catch 會在 setTimeout 回調(diào)之前執(zhí)行蚕钦;但是若異步操作拋出錯誤的回調(diào)是在 Promise 的 catch 之前執(zhí)行的,其實還是可以被 catch 所捕獲到的鹅很,比如 Promise 的 then 方法所拋出的錯誤:
let p = Promise.resolve();
let p1 = new Promise(function (resolve, reject) {
p.then(()=>{
throw 123;
}).catch(e => {
reject(e);
});
});
p1.catch(err => {
console.log(err); // 123嘶居,錯誤成功被捕獲
});
- 一旦 Promise 對象已經(jīng) resolve,其后的運行時錯誤將被忽略:
let p = new Promise((resolve, reject) => {
resolve();
throw "error";
});
p.catch(err => {
console.log("catch " + err); // 不會被執(zhí)行
});
return的值
與 then 方法相同,執(zhí)行后會 return 一個新的 Promise 對象邮屁,以實現(xiàn)鏈式調(diào)用整袁,你可以顯式的 return 一個 Promise 對象,若不顯式的 return 則會 return 一個以 undefined 值 resolve 的 Promise 對象佑吝;
let p = Promise.reject("error");
// catch
p.catch(err => {
console.log("catch " + err); // catch error
// 這里會默認return Promise.resolve(undefined);
}).then(res => {
console.log(res); // undefined
});
let p2 = Promise.resolve("success");
// then
p2.catch(err => { // 由于p2正常resolve坐昙,所以此處不會執(zhí)行
console.log("catch " + err);
}).then(res => { // 由于前一個catch未執(zhí)行,所以此處調(diào)用then的還是p2
console.log(res); // success
// 這里會默認return Promise.resolve(undefined);
}).then(res => {
console.log(res); // undefined
});