一、概念
Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。
Promise對象是一個構造函數,用來生成Promise實例。其本身有all、reject、resolve等方法,原型prototype上有catch、finally、then等方法,所以用Promise new出來的對象肯定有catch、finally、then方法。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。
二、用法
Promise對象代表一個異步操作,有三種狀態:pending(進行中)、fulfilled(已成功)、rejected(已失敗)。只有異步操作的結果可以決定當前是哪一種狀態,任何其它操作都無法改變這個狀態。
1、基本用法
const promise = new Promise((resolve, reject)=>{
if(/*異步操作成功*/){
resolve()
}else{
reject(error)
}
})
Promise構造函數接受一個函數作為參數,該函數的兩個參數分別是resolve和reject。
resolve:將Promise對象的狀態從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,并將異步操作的結果,作為參數傳遞出去;
reject:將Promise對象的狀態從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,并將異步操作報出的錯誤,作為參數傳遞出去。
2、then方法
Promise實例生成以后,可以用then方法分別指定resolved狀態和rejected狀態的回調函數。
promiseFun(){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log('執行完')
const arr1 = [{name: '張三',age: '24'}]
resolve(arr1)
},2000)
})
}
promiseFun().then((res)=>{
// success
console.log(res) // [{name: '張三',age: '24'}]
})
以上代碼運行輸出的結果順序是這樣的:
通過上述代碼,我們可知,then里邊的函數就跟我們平時的回調函數一樣,能夠在異步任務執行完成后再被執行,就是能把原來的回調寫法分離出來,在異步操作執行完后,用鏈式調用的方式執行回調函數。
2、catch方法
用來指定reject的回調函數
promiseFun(){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log('執行完')
const arr1 = [{name: '張三',age: '24'}]
reject(`執行失敗${arr1}`)
},2000)
})
}
promiseFun().catch((e)=>{
// error
console.log(e) // `執行失敗 [{name: '張三',age: '24'}]
})
3、all方法
Promise.all()方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例。
function promiseFun1(){
return new Promise(function(resolve, reject){
setTimeout(function(){
console.log('1、執行完')
const arr1 = [{name: '張三',age: '24'}]
resolve(arr1)
},1000)
})
}
function promiseFun2(){
return new Promise(function(resolve, reject){
setTimeout(function(){
console.log('2、執行完')
const arr1 = '哈哈哈'
resolve(arr1)
},2000)
})
}
function promiseFun3(){
return new Promise(function(resolve, reject){
setTimeout(function(){
console.log('3、執行完')
const arr1 = [{name: '張三',age: '24'}]
resolve(arr1)
},3000)
})
}
Promise.all([promiseFun1(),promiseFun2(),promiseFun3()]).then((results)=>{console.log(results)})
輸出結果:
注意:Promise 新建后就會立即執行,所以會先打印執行完,等到所有Promise完成狀態的改變后才執行then。
在用Promise的時候一般是包在一個函數中,需要的時候去運行這個函數
4、race用法
在all中的回調函數中,等到所有的Promise都執行完,再來執行回調函數,race則不同它等到第一個Promise改變狀態就開始執行回調函數。
我們把setTimeout的時間改一下:
function promiseFun1(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
console.log('1、執行完')
const arr1 = [{name: '張三',age: '24'}]
resolve(arr1)
},500)
})
return p
}
function promiseFun2(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
console.log('2、執行完')
const arr1 = '哈哈哈'
resolve(arr1)
},500)
})
return p
}
function promiseFun3(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
console.log('3、執行完')
const arr1 = '33333'
resolve(arr1)
},100)
})
return p
}
Promise.race([promiseFun1(),promiseFun2(),promiseFun3()]).then((results)=>{console.log('hhh=',results)})
結果輸出:
由此得出:then是以誰執行的最慢,就以誰為準執行回調;race是以誰執行的最快,就以誰為準執行回調
三、使用場景
Promise.prototype.then:
1、下個請求依賴上個請求的結果
2、接口返回的數據量比較大,在一個then 里面處理 顯得臃腫,多個渲染數據分別給個then,讓其各司其職
Promise.all:
1、一個頁面,有多個請求,我們需要所有的請求都返回數據后再一起處理渲染
2、合并請求結果并處理錯誤
3、驗證多個請求結果是否都是滿足條件
Promise.race:
1、請求超時