1、什么是Promise
Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。
這么說可能不夠直觀的理解,看下面的兩個例子
// callback回調函數 function getCallback(n,callback) { setTimeout(() => { var num = 2*n console.log('num',num) callback(num) },2000) } getCallback(3,function callback(n) { console.log('n',n) }) // Promise函數的基礎用法(等同於上面的回調函數) function runPro(n){ let p = new Promise((resolve,reject) => { setTimeout(() => { var num = 2*n console.log('num',num) resolve(num) },2000) }) return p } runPro(3).then((res) => { console.log('res',res) })
這么看是不是覺得Promise並沒有什么特別的,而且還要費勁封裝,有這功夫用回調函數就好了,那么在看下面的例子
// 三層callback回調函數(傳說的回調地獄) function getCallback0(n,callback1) { setTimeout(() => { var num0 = 2*n console.log('num0',num0) callback1(num0,function callback2(params,callback3) { let num2 = params + 1 console.log('num2',num2) callback3(num2) }) },2000) } getCallback0(3,function callback1(n,callback2) { let num1 = n+1 console.log('num1',num1) callback2(num1,function callback3(params) { let num3 = params + 1 console.log('num3',num3) } ) }) // 三層Promise(等同於上面的回調函數) function runPro0(n){ let p = new Promise((resolve,reject) => { setTimeout(() => { var num0 = n*2 console.log('num0',num0) resolve(num0) },2000) }) return p } runPro0(3) .then((res) => { // console.log('res',res) let Pro1 = new Promise((resolve,reject) =>{ var num1 = res+1 console.log('num1',num1) resolve(num1) }) return Pro1 }) .then((res) =>{ // console.log('res',res) let Pro2 = new Promise((resolve,reject) =>{ var num2 = res+1 console.log('num2',num2) resolve(num2) }) return Pro2 }) .then((res) =>{ var num3 = res+1 console.log('num3',num3) // 如果需要可以繼續回調 })
通過上面的對比可以很清除的看出,用Promise處理異步事件更加簡潔直觀
2、基礎用法
const p = new Promise(function(resolve,reject){ if(success){ resolve('成功的結果') }else{ reject('失敗的結果') } }) p.then(function (res) { // 接收resolve傳來的數據,做些什么 },function (err) { // 接收reject傳來的數據,做些什么 }) p.catch(function (err) { // 接收reject傳來的數據或者捕捉到then()中的運行報錯時,做些什么 })
p.finally(function(){
// 不管什么狀態都執行
})
3、Promise的相關方法
Promise.prototype.then() Promise.prototype.catch() Promise.prototype.finally() Promise.resolve() Promise.reject() Promise.all() Promise.race()
由代碼可以看出.then() .catch() .finally()都是定義在原型對象上的
4、then 的用法
由上面的基礎用法代碼可以看出.then()接收兩個參數,第一個是resolved狀態的回調函數,第二個是rejected狀態的回調函數
5、catch的用法
.catch方法是.then(null, rejection)的別名,用於指定發生錯誤時的回調函數。
6、finally的用法
.finally方法用於指定不管 Promise 對象最后狀態如何,都會執行的操作。該方法是 ES2018 引入標准的。
7、all的用法
Promise的all方法提供了並行執行異步操作的能力,並且在所有異步操作執行完后才執行回調,all接收一個數組參數,里面的值最終都算返回Promise對象。這樣,三個異步操作的並行執行的,等到它們都執行完后才會進到then里面。那么,三個異步操作返回的數據哪里去了呢?都在then里面呢,all會把所有異步操作的結果放進一個數組中傳給then。
(1)只有getNumber1、getNumber2、getNumber3的狀態都變成fulfilled,Promise的狀態才會變成fulfilled,此時getNumber1、getNumber2、getNumber3的返回值組成一個數組,傳遞給Promise的回調函數。
(2)只要getNumber1、getNumber2、getNumber3之中有一個被rejected,Promise的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給Promise的回調函數。
function getNumber1(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('1') resolve('隨便什么數據1'); }, 1000); }); return p; } function getNumber2(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('2') reject('隨便什么數據2'); }, 2000); }); return p; } function getNumber3(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('3') reject('隨便什么數據3'); }, 3000); }); return p; } Promise.all([getNumber1(),getNumber2(),getNumber3()]) .then(function(res){ console.log('res',res) console.log('res',res[2].data) },function (err){ console.log('err',err) }) .catch(function(err2){ console.log('err2',err2) })
8、race的用法
Promise.race方法同樣是將多個 Promise 實例,包裝成一個新的 Promise 實例。
不過只要getNumber1、getNumber2、getNumber3之中有一個實例率先改變狀態,Promise的狀態就跟着改變。那個率先改變的 Promise 實例的返回值,就傳遞給Promise的回調函數。
注意:
1、Promise定義后就執行,所以通常用函數進行分裝
2、Promise.all()中的參數是以一個數組傳入的