1.什么是Promise?
Promise是抽象異步處理對象以及對其進(jìn)行各種操作的組件。
2.三種類型
Constructor是其中一種:
Promise類似于 XMLHttpRequest,從構(gòu)造函數(shù) Promise 來創(chuàng)建一個(gè)新建新promise對象作為接口。
要想創(chuàng)建一個(gè)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); 的返回值也是一個(gè)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)用,都返回了一個(gè)新的promise對象。
6.1 我們說過 .catch 也可以理解為 promise.then(undefined, onRejected) 。
then不能進(jìn)行錯(cuò)誤處理的onRejected
function throwError(value) {
// 拋出異常
throw new Error(value);
}
// <1> onRejected不會被調(diào)用
function badMain(onRejected) {
return Promise.resolve(42).then(throwError, onRejected);
}
// <2> 有異常發(fā)生時(shí)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 是一個(gè)不太好的實(shí)現(xiàn)方式(但也不是說它有多壞), goodMain 則是一個(gè)能非常好的進(jìn)行錯(cuò)誤處理的版本。
為什么說 badMain 不好呢?,因?yàn)殡m然我們在 .then 的第二個(gè)參數(shù)中指定了用來錯(cuò)誤處理的函數(shù),但實(shí)際上它卻不能捕獲第一個(gè)參數(shù) onFulfilled 指定的函數(shù)(本例為 throwError )里面出現(xiàn)的錯(cuò)誤。
也就是說,這時(shí)候即使 throwError 拋出了異常,onRejected 指定的函數(shù)也不會被調(diào)用(即不會輸出"BAD"字樣)。
與此相對的是, goodMain 的代碼則遵循了 throwError→onRejected 的調(diào)用流程。 這時(shí)候 throwError 中出現(xiàn)異常的話,在會被方法鏈中的下一個(gè)方法,即 .catch 所捕獲,進(jìn)行相應(yīng)的錯(cuò)誤處理。
.then 方法中的onRejected參數(shù)所指定的回調(diào)函數(shù),實(shí)際上針對的是其promise對象或者之前的promise對象,而不是針對 .then 方法里面指定的第一個(gè)參數(shù),即onFulfilled所指向的對象,這也是 then 和 catch 表現(xiàn)不同的原因。
``
2.10.2. 總結(jié)
這里我們又學(xué)習(xí)到了如下一些內(nèi)容。
-
使用
promise.then(onFulfilled, onRejected)的話- 在
onFulfilled中發(fā)生異常的話,在onRejected中是捕獲不到這個(gè)異常的。
- 在
-
在
promise.then(onFulfilled).catch(onRejected)的情況下-
then中產(chǎn)生的異常能在.catch中捕獲
-
-
.then和.catch在本質(zhì)上是沒有區(qū)別的- 需要分場合使用。
我們需要注意如果代碼類似 badMain 那樣的話,就可能出現(xiàn)程序不會按預(yù)期運(yùn)行的情況,從而不能正確的進(jìn)行錯(cuò)誤處理。
7.使用 reject 會比使用 throw 安全
在 then 中使用reject的方法
8.then原理
在 then 中注冊的回調(diào)函數(shù)可以通過 return 返回一個(gè)值,這個(gè)返回值會傳給后面的 then 或 catch 中的回調(diào)函數(shù)。
而且return的返回值類型不光是簡單的字面值,還可以是復(fù)雜的對象類型,比如promise對象等。
這時(shí)候,如果返回的是promise對象的話,那么根據(jù)這個(gè)promise對象的狀態(tài),在下一個(gè) then 中注冊的回調(diào)函數(shù)中的onFulfilled和onRejected的哪一個(gè)會被調(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 的哪個(gè)方法會被調(diào)用
});
return retPromise;
}).then(onFulfilled, onRejected);
###后面的then調(diào)用哪個(gè)回調(diào)函數(shù)是由promise對象的狀態(tài)來決定的
也就是說,這個(gè) retPromise 對象狀態(tài)為Rejected的時(shí)候,會調(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);