Promise物件
一、什麼是Promise?
- Promise是一種非同步操作的解決方案,將寫法複雜的傳統的回撥函式和監聽事件的非同步操作,用同步程式碼的形式表達出來。
- Promise避免了多級非同步操作的回撥函式巢狀。
- Promise最早是一個函式庫,現在已經被ES6寫入標準用法。
- Promise是一種建構函式。
- Promise例項建立後會立即執行。
二、Promise的基本使用
console.log("1")
new Promise((resolve,reject)=>{ // resolve,reject是形式引數,可以是任意寫法,如(res, rej),預設第一個引數實現的是resolve功能;第二個引數實現的是reject功能。
console.log("2")
resolve("成功了")
console.log("3") //resolve()不同於return, resolve()執行完成後後面的程式碼還會執行。
})
執行結果:
1
2
3
Promise {<fulfilled>: "成功了"}
// 一般狀態改變後的操作放在then回撥函式中
// 所以最好寫成
new Promise((resolve,reject)=>{
console.log("2")
return resolve("成功了")
console.log("3") //不再執行,最好不要在狀態改變後新增操作
})
//resolve()不同於return, resolve()執行完成後後面的程式碼還會執行。
建立例項如下: const p = new Promise((resolve,reject)=>{ //需要實現的非同步操作
........
........
if("success") resolve(value)
// resolve是js引擎提供定的成功後呼叫的函式,作用就是手動將該promise的狀態由,pending(未完成)變為fulfilled(非同步操作成功),然後立即觸發then中的成功回撥函式
// value值是非同步操作的結果,要傳給後面的回撥函式的值
// 值的內容可以根據業務需求自己定;可以是值(普通物件,函式,字元,數字等)也可以是Promise物件
else reject(new Error)
//reject也是js引擎提供的失敗後呼叫的函式,作用就是手動將狀態由pending變為
//ejected(非同步操作失敗),引數是丟擲的異常。然後才能觸發then中的錯誤回撥函式或者catch中的回撥函式
})
三、Promise的例項方法
1. Promise.prototype.then()
是什麼:then方法是Promise建構函式原型物件上的方法。
作用: 為例項狀態改變時新增回撥函式(相當於例項狀態變化的監聽函式)。
(1).then方法接受兩個回撥函式作為引數,
第一個函式是例項狀態變為resolved(fulfilled)時的回撥函式;
第二個函式是例項狀態變為rejected時的回撥函式。
p.then(function(value){
// 前面例項中resolve方法執行後觸發該方法,即狀態為fulfilled(resolved)狀態時觸發的回撥函式
// value值就是resolve的引數值
},function(err) {
// 前面例項中reject方法執行後會觸發該方法,即狀態為rejected時
})
(2).then方法返回一個新的Promise例項,所以可以採用鏈式寫法;
then方法的第一個回撥函式的返回值,即return的值作為下一個then方法裡面的函式傳參。
如果返回值不是Promise物件,會觸發下一個then方法的第一個回撥函式, 並且返回值作為回撥函式的引數;
2. Promise.prototype.catch()
是什麼:Promise原型上的catch方法,相當於.then(null/undefined, () => {}),所以返回的也是promise,後面還可以跟then或者catch,只在rejected狀態觸發。
作用: 它可以捕獲所有之前執行的promise中的錯誤,最好所有的promise都在最後使用catch方法,不要在then方法中寫第二個回撥函式
p.then((val) => {
throw new Error("failed");
}).then((val) => {
// TODO
}).catch((err) => {
console.log(err); // Error: failed 捕獲內部異常
})
3. Promise.prototype.finally()
作用:不管狀態(不能是pending)如何,都會執行的方法。
new Promise((resolve,reject) => {
// 狀態修改為resolved或者rejected
}).finally(() => {...} )
finally方法最後返回一個promise例項,回撥函式不接受任何值,return方法也被忽略。
但是會預設返回之前的例項物件傳遞的引數。
應用:
如處理檔案完成後,不論成功與否都關閉檔案。
四、Promise常用的兩個靜態方法
1、Promise.all()
接受一個陣列(每個引數都是promise例項)作為引數。
如果引數不是promise例項,系統會自動呼叫Promise.resolve()方法,將引數轉為promise例項。
返回一個陣列,引數例項的返回值作為對應的回撥函式的引數
const arr = [1,2];
Promise.all(arr) // 相當於 arr.map(item => Promise.resolve(item))
.then(data => console.log('data-->',data))
//執行結果如下:
// data--> [1,2]
2、Promise.race()
引數性質和Promise.all()一樣,都是以引數為Promise例項的陣列為引數。
返回一個新的Promise例項。
作用不一樣:
只要有一個引數例項的狀態發生改變,新的例項的狀態隨之改變,引數例項的返回值作為對應的回撥函式的引數。