Promise是一種異步編程的解決方案,相比傳統回調函數更合理.編程
1.Promise當即執行性promise
let p = new Promise((resolve, reject) => { console.log('當即執行!'); resolve('返回成功!') }); console.log('promise後執行!'); p.then(value => { console.log(value) });
控制檯輸出:異步
"當即執行!" "promise後執行!" "返回成功!"
Promise對象表示將來發生的事件,在建立promise時,做爲promise參數傳入的函數是會被當即執行的,只是其中執行的代碼能夠是異步代碼.有些人會認爲,當promise對象調用then方法時,promise接受的函數纔會執行,這是錯誤的.因此,代碼中當即執行!
先於promise後執行!
輸出.異步編程
2.Promise的三種狀態.函數
let p1 = new Promise((reslove, reject) => { reslove(1); }); let p2 = new Promise((reslove, reject) => { setTimeout(() => { reslove(2); }, 500); }); let p3 = new Promise((reslove, reject) => { setTimeout(() => { reject(3); }, 500); }); console.log(p1); console.log(p2); console.log(p3); setTimeout(() => { console.log(p2); }, 1000); setTimeout(() => { console.log(p3); }, 1000); p1.then(value => { console.log(value); }); p2.then(value => { console.log(value); }); p3.catch(err => { console.log(err); });
控制檯輸出:code
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1} Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} 1 2 3 Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2} Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}
Promise內部實現是一個狀態機.Promise有三種狀態: pending,resolved,rejected.當Promise剛建立完成時,處於pending狀態;當Promise中的函數參數執行了resolve後,Promise由pending狀態變成resloved狀態;若是Promise的函數參數中執行的是reject方法,那麼Promise會有pending狀態變成rejected狀態.對象
3.Promise狀態不可逆性.事件
let p1 = new Promise((reslove, reject) => { reslove('成功1!'); reslove('成功2!'); }); let p2 = new Promise((reslove, reject) => { reslove('成功!'); reject('失敗!'); }); p1.then(value => { console.log(value); }); p2.then(value => { console.log(value); });
控制檯輸出:回調函數
"成功1!" "成功!"
Promise的狀態一旦變成resolved或rejected時,Promise的狀態和值就固定下來了,不管後續再怎麼調用reslove或是reject方法,都不能改變它的狀態和值.因此,p1中reslove('成功2!')並不能將p1的值更改成成功2!
,p2中reject('失敗!')也不能將p2的狀態由resolved改變爲rejected.同步
4.鏈式調用.
let p = new Promise((resolve, reject) => { resolve(1); }); p.then(value => { console.log(value); return value * 2; }).then(value => { console.log(value); }).then(value => { console.log(value); return Promise.resolve('resolve'); }).then(value => { console.log(value); return Promise.reject('reject'); }).then(value => { console.log(`resolve: ${value}`); }, err => { console.log(`reject: ${err}`); })
控制檯輸出:
1 2 undefined "resolve" "reject: reject"
Promise對象的then方法返回一個新的Promise對象,因此能夠經過鏈式調用then方法.then方法接受兩個函數做爲參數,第一個參數是Promise執行成功時的回調,第二個參數是Promise執行失敗時的回調.兩個函數只會有一個被調用,函數返回值將用做建立then返回的Promise對象.這兩個參數的返回值能夠是下面三種狀況的一種:
①:return一個同步的值,或者undefined(當沒有返回一個有效值時,默認返回undefined),then方法將返回一個resloved狀態的Promise對象,Promise對象的值就是這個返回值. ②:return另外一個Promise,then方法將根據這個Promise的狀態和值建立一個新的Promise對象返回. ③:throw一個同步異常,then方法將返回一個rejected狀態的Promise,值是該異常.
根據以上分析,代碼中的第一個then會返回一個值爲2(1 * 2),狀態爲resolved的Promise對象,於第二個then輸出的值爲2.第二個then中沒有返回值,所以將返回默認的undefined,因而在第三個then中輸出的undefined.第三個then和第四個then中分別返回一個狀態是resloved的Promise和一個狀態是rejected的Promise,依次由第四個then中的成功回調函數和第五個then中的失敗回調函數處理.
5.Promise then()回調異步性.
let p = new Promise((resolve, reject) => { resolve('成功!'); }); p.then(value => { console.log(value); }); console.log("誰先執行?")
控制檯輸出:
"誰先執行?" "成功!"
Promise接受的函數參數是同步執行的,可是then方法中的回調函數則是異步的,所以,成功!
會在後面輸出.
6.Promise中的異常.
let p1 = new Promise((resolve, reject) => { foo.bar(); resolve(1); }); p1.then(value => { console.log(`p1 then value: ${value}`); }, err => { console.log(`p1 then err: ${err}`); }).then(value => { console.log(`p1 then then value: ${value}`); }, err => { console.log(`p1 then then err: ${err}`); }); let p2 = new Promise((resolve, reject) => { resolve(2); }); p2.then(value => { console.log(`p2 then value: ${value}`); foo.bar(); }, err => { console.log(`p2 then err: ${err}`); }).then(value => { console.log(`p2 then then value: ${value}`); }, err => { console.log(`p2 then then err: ${err}`); return 1; }).then(value => { console.log(`p2 then then then value: ${value}`); }, err => { console.log(`p2 then then then err: ${err}`); });
控制檯輸出:
p1 then err: ReferenceError: foo is not defined p2 then value: 2 p1 then then value: undefined p2 then then err: ReferenceError: foo is not defined p2 then then then value: 1
Promise中的異常由then參數中的第二個回調函數(Promise執行失敗的回調)處理,異常信息將做爲Promise的值.異常一旦獲得處理,then返回後續的Promise對象將恢復正常,並會被Promise執行成功的回調函數處理.另外,須要注意p1,p2多級then的回調函數是交替執行的,這正是由Promise then回調的異步性決定的.
7.Promise.reslove().
let p1 = Promise.resolve(1); let p2 = Promise.resolve(p1); let p3 = new Promise((resolve, reject) => { resolve(1); }); let p4 = new Promise((resolve, reject) => { resolve(p1); }); console.log(p1 === p2); console.log(p1 === p3); console.log(p1 === p4); console.log(p3 === p4); p4.then(value => { console.log(`p4=${value}`) }); p2.then(value => { console.log(`p2=${value}`) }); p1.then(value => { console.log(`p1=${value}`) });
控制檯輸出:
true false false false p2=1 p1=1 p4=1
Promise.resolve(...) 能夠接受一個值或者是一個Promise對象做爲參數.當參數是普通值時,它返回一個resolved狀態的Promise對象,對象的值就是這個參數;當參數是一個Promise對象時,它直接返回這個Promise參數.因此p1===p2.但經過new建立的Promise對象都是一個新的對象,因此後面三個比較結果都是false.另外,爲何p4的then最早調用,可是在控制檯上是最後輸出結果的呢?由於p4中resolve接受的參數是一個Promise對象p1,reslove會對p1進行解析,獲取p1的狀態和值,可是這個過程是異步的.
8.resolve v reject.
let p1 = new Promise((resolve, reject) => { resolve(Promise.resolve('resolve')); }); let p2 = new Promise((resolve, reject) => { resolve(Promise.reject('reject')); }); let p3 = new Promise((resolve, reject) => { reject(Promise.resolve('resolve')); }); p1.then(value => { console.log(`p1 fulfilled: ${value}`); }, err => { console.log(`p1 rejected: ${err}`); }); p2.then(value => { console.log(`p2 fulfilled: ${value}`); }, err => { console.log(`p2 rejected: ${err}`); }); p3.then(value => { console.log(`p3 fulfilled: ${value}`); }, err => { console.log(`p3 rejected: ${err}`); });
控制檯輸出:
p3 rejected: [object Promise] p1 fulfilled: resolve p2 rejected: reject
Promise回調函數中的第一個參數resolve,會對Promise執行解析,即resolve的參數是Promise對象時,resolve會解析獲取這個Promise對象的狀態和值,但這個過程是異步的.p1解析後,獲取到Promise對象的狀態是resolved,所以第一個回調被執行也就是獲取value的回調;p2解析後,獲取到Promise對象的狀態rejected,所以rejected回調執行.但Promise回調函數中的第二個參數reject不具有解析能力,reject的參數會直接傳遞給then方法中的rejected回調,所以,即便p3 reject接受了一個resolved狀態的Promise,then方法中調用的依然是rejected,而且參數就是reject接受到的Promise對象.