1.什么是Promise?
Promise是抽象異步處理對象以及對其進(jìn)行各種操作的組件。
2.三種類型
Constructor是其中一種:
Promise類似于 XMLHttpRequest,從構(gòu)造函數(shù) Promise 來創(chuàng)建一個新建新promise對象作為接口叁鉴。
要想創(chuàng)建一個promise對象承绸、可以使用new來調(diào)用Promise的構(gòu)造器來進(jìn)行實(shí)例化奋早。
var promise = new Promise(function(resolve, reject) {
// 異步處理
// 處理結(jié)束后兜粘、調(diào)用resolve 或 reject
});
//可以使用then,catch實(shí)例化:
成功resolve():
promise.then(onFulfilled, onRejected)
失敗reject()有兩種寫法绞绒,后者更直觀:
promise.then(undefined, onRejected) == promise.catch(onRejected)
3.Promise創(chuàng)建和處理方法:
4.new Promise()
方法的快捷方式
靜態(tài)方法Promise.resolve(value)
可以認(rèn)為是 new Promise()
方法的快捷方式拦耐。
###比如 Promise.resolve(42); 可以認(rèn)為是以下代碼的語法糖耕腾。
new Promise(function(resolve){
resolve(42);
});
###方法 Promise.resolve(value); 的返回值也是一個promise對象,所以我們可以像下面那樣接著對其返回值進(jìn)行 .then 調(diào)用杀糯。
Promise.resolve(42).then(function(value){
console.log(value);
});
5.Promise方法鏈
aPromise.then(function taskA(value){
// task A
}).then(function taskB(vaue){
// task B
}).catch(function onRejected(error){
console.log(error);
});
function taskA() {
console.log("Task A");
}
function taskB() {
console.log("Task B");
}
function onRejected(error) {
console.log("Catch Error: A or B", error);
}
function finalTask() {
console.log("Final Task");
}
var promise = Promise.resolve();
promise
.then(taskA)
.then(taskB)
.catch(onRejected)
.then(finalTask);
6.不管是 then 還是 catch 方法調(diào)用扫俺,都返回了一個新的promise對象。
6.1 我們說過 .catch
也可以理解為 promise.then(undefined, onRejected)
固翰。
then不能進(jìn)行錯誤處理的onRejected
function throwError(value) {
// 拋出異常
throw new Error(value);
}
// <1> onRejected不會被調(diào)用
function badMain(onRejected) {
return Promise.resolve(42).then(throwError, onRejected);
}
// <2> 有異常發(fā)生時onRejected會被調(diào)用
function goodMain(onRejected) {
return Promise.resolve(42).then(throwError).catch(onRejected);
}
// 運(yùn)行示例
badMain(function(){
console.log("BAD");
});
goodMain(function(){
console.log("GOOD");
});
在上面的代碼中狼纬, badMain 是一個不太好的實(shí)現(xiàn)方式(但也不是說它有多壞)羹呵, goodMain 則是一個能非常好的進(jìn)行錯誤處理的版本。
為什么說 badMain 不好呢疗琉?冈欢,因?yàn)殡m然我們在 .then 的第二個參數(shù)中指定了用來錯誤處理的函數(shù),但實(shí)際上它卻不能捕獲第一個參數(shù) onFulfilled 指定的函數(shù)(本例為 throwError )里面出現(xiàn)的錯誤盈简。
也就是說凑耻,這時候即使 throwError 拋出了異常,onRejected 指定的函數(shù)也不會被調(diào)用(即不會輸出"BAD"字樣)柠贤。
與此相對的是香浩, goodMain 的代碼則遵循了 throwError→onRejected 的調(diào)用流程。 這時候 throwError 中出現(xiàn)異常的話臼勉,在會被方法鏈中的下一個方法弃衍,即 .catch 所捕獲,進(jìn)行相應(yīng)的錯誤處理坚俗。
.then 方法中的onRejected參數(shù)所指定的回調(diào)函數(shù)镜盯,實(shí)際上針對的是其promise對象或者之前的promise對象,而不是針對 .then 方法里面指定的第一個參數(shù)猖败,即onFulfilled所指向的對象速缆,這也是 then 和 catch 表現(xiàn)不同的原因。
``
2.10.2. 總結(jié)
這里我們又學(xué)習(xí)到了如下一些內(nèi)容恩闻。
-
使用
promise.then(onFulfilled, onRejected)
的話- 在
onFulfilled
中發(fā)生異常的話艺糜,在onRejected
中是捕獲不到這個異常的。
- 在
-
在
promise.then(onFulfilled).catch(onRejected)
的情況下-
then
中產(chǎn)生的異常能在.catch
中捕獲
-
-
.then
和.catch
在本質(zhì)上是沒有區(qū)別的- 需要分場合使用幢尚。
我們需要注意如果代碼類似 badMain
那樣的話破停,就可能出現(xiàn)程序不會按預(yù)期運(yùn)行的情況,從而不能正確的進(jìn)行錯誤處理尉剩。
7.使用 reject 會比使用 throw 安全
在 then 中使用reject的方法
8.then原理
在 then 中注冊的回調(diào)函數(shù)可以通過 return 返回一個值真慢,這個返回值會傳給后面的 then 或 catch 中的回調(diào)函數(shù)。
而且return的返回值類型不光是簡單的字面值理茎,還可以是復(fù)雜的對象類型黑界,比如promise對象等。
這時候皂林,如果返回的是promise對象的話朗鸠,那么根據(jù)這個promise對象的狀態(tài),在下一個 then 中注冊的回調(diào)函數(shù)中的onFulfilled和onRejected的哪一個會被調(diào)用也是能確定的础倍。
也許實(shí)際中我們可能不常使用 reject 烛占,但是比起來不假思索的使用 throw 來說,使用 reject 的好處還是很多的沟启。
var promise = Promise.resolve();
promise.then(function () {
var retPromise = new Promise(function (resolve, reject) {
// resolve or reject 的狀態(tài)決定 onFulfilled or onRejected 的哪個方法會被調(diào)用
});
return retPromise;
}).then(onFulfilled, onRejected);
###后面的then調(diào)用哪個回調(diào)函數(shù)是由promise對象的狀態(tài)來決定的
也就是說忆家,這個 retPromise 對象狀態(tài)為Rejected的時候犹菇,會調(diào)用后面then中的 onRejected 方法,這樣就實(shí)現(xiàn)了即使在 then 中不使用 throw 也能進(jìn)行reject處理了弦赖。
var onRejected = console.error.bind(console);
var promise = Promise.resolve();
promise.then(function () {
var retPromise = new Promise(function (resolve, reject) {
reject(new Error("this promise is rejected"));
});
return retPromise;
}).catch(onRejected);
//簡寫
var onRejected = console.error.bind(console);
var promise = Promise.resolve();
promise.then(function () {
return Promise.reject(new Error("this promise is rejected"));
}).catch(onRejected);