ES6中的Promise的用法總結


第一部分、什么是Promise ? 

Promise是ES6中提供的一個異步編程的解決方案,Promise本身是一個構造函數

 

typeof Promise  //  function

 

一般情況下 我們在開發中會使用 new Promise() 調用構造函數,創建一個新的Promise對象, Promise對象有兩個特點

1、對象的狀態不受外界影響。Promise對象是一個異步操作,有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。

只有異步操作的結果,可以決定Promise是哪一種狀態,任何其他操作都無法改變這個狀態

2、一旦Promise狀態改變,就不會再有變化,任何時候都可以得到這個結果。Promise對象的狀態改變,只有兩種可能:從pending變為fulfilled 或者 從pending變為rejected。只要這兩種情況發生,狀態就不會再變了,會一直保持這個結果,這時就稱為 resolved(已定型)。如果改變已經發生了,你再對Promise對象添加回調函數,也會立即得到這個結果。這與事件(Event)不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的

使用Promise的好處,就是在處理異步程序時,將異步操作隊列化,按照期望的順序執行,返回符合預期的結果,這樣即使是多重異步操作,也可以方便的使用Promise進行鏈式調用

3、Promise也有一些缺點。

首先,無法取消Promise,一旦新建它就會立即執行,無法中途取消。其次,如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。第三,當處於pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)

第二部分、循序漸進的介紹Promise的用法

1、最簡單的用法

 

const  p =  new Promise((resolve, reject) => {
    // 在這里執行一個異步操作吧
    setTimeout(function(){
        console.log(1234)
        resolve(1234)
    }, 3000)
})

// 創建這個Promise之后, 3秒后 會控制台輸出1234,並且3秒后得到了一個結果,異步程序返回了1234這個結果,那么

p.then((res) => {
    console.log(res)
})

// 控制台會輸出1234 ,promise的then方法 會再次返回一個promise,不過值默認undefined

p.then((res) => {
    console.log(res)
}).then((res)=>{
   console.log(res)    
})

// 1234, undefined

 

2、reject的用法

 

const p2 = new Promise((resolve, reject)=>{
    // 執行一個異步操作
    setTimeout(function(){
        console.log(1024)
        reject(1024)
    }, 3000)
})

p2.then(res=>{
    console.log(res)
}).catch(res=>{
    console.error(res)    
})

//  3秒之后 輸出錯誤 1024

 

3、all的用法, 多個異步操作進行數組形式的返回值處理,當所有的異步都resolve時,可以執行then操作,當其中一個或多個reject時,所有的異步都會停止調用,直接返回最早發生錯誤的那個結果

 

const pa = new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pa')
        resolve('pa')
    },3000)
})

const pb = new Promise((resolve, reject)=>{
   setTimeout(function(){
        console.log('pb')
        resolve('pb')
    },4000)
})

const pc = new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pc')
        resolve('pc')
    },5000)
})

const pd =  new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pd')
        reject('pd')
    },5000)
})


Promise.all([pa, pb, pc]).then((res)=>{
     console.log('成功' + res)
})

// 3秒后 pa  4秒后pb 5秒后 pc pd 然后輸出成功pa,pb,pc

Promise.all([pa, pb, pd]).then((res)=>{
    console.log('成功' + res)
}).catch(err=>{
    console.log('失敗' + err)
})

// 輸出失敗pd

 

4、race的用法, 語法和all()一樣,但是返回值有所不同,race根據傳入的多個Promise實例,只要有一個實例resolve或者reject,就只返回該結果,其他實例不再執行,也就是說多個異步程序,只返回響應最快的那個異步程序,不論成功或者失敗,就把最快響應的返回值返回,后面的異步程序不再執行

 

const pa = new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pa')
        resolve('pa')
    },3000)
})

const pb = new Promise((resolve, reject)=>{
   setTimeout(function(){
        console.log('pb')
        resolve('pb')
    },4000)
})

const pc = new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pc')
        resolve('pc')
    },5000)
})

const pd =  new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pd')
        reject('pd')
    },5000)
})

const pe =  new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pe')
        reject('pe')
    },2000)
})

const pf =  new Promise((resolve, reject)=>{
    setTimeout(function(){
        console.log('pf')
        resolve('pf')
    },2000)
})

Promise.race([pa, pe, pf]).then(res=>{
    console.log('成功' + res)
}).catch(res=>{
    console.log('失敗' + res)
})


Promise.race([pd, pe]).then().catch(res=>{
    console.log('失敗' + res)
})

// 2秒后 輸出 失敗 + pe 

// 2秒后 輸出 失敗 +  pe

 

5、resolve方法,

Promise的resolve方法,用於將非Promise類型的對象,轉為Promise對象,這樣就可以調用Promise原型對象上的方法了

 

Promise.resolve(x) 

上面的寫法等價於 

new Promise(resolve => { resolve(x)})

 

resolve的參數分為幾種不同的情況:

(1)沒有參數,如果沒有參數,這直接返回一個resolved狀態的Promise對象 

const p = Promise.resolve()

相當於 

const p = new Promise(resolve => {
    resolve undefined
})

p.then(res=>{
    console.log(res)
})

// 輸出 undefined

(2) 參數是一個不具有then方法的對象,或者是一個基數數據類型的值,則Promise.resolve方法返回一個新的 Promise 對象,狀態為resolved,值為指定值

const p = Promise.resolve('pro')

p.then((x) =>{
    console.log(x)
})

// 輸出 'pro'

 

(3) 參數是一個具有then方法的對象,Promise.resolve方法會將這個對象轉為 Promise 對象,然后就立即執行thenable對象的then方法。

const obj = {
    then: function(resolve, reject) {
        resolve(100)
    }
}

const p  = Promise.resolve(obj)

p.then((res) => {
    console.log(res)
})

// 輸出 100

 

(4)參數是一個Promise對象,那么將原封不動的返回這個Promise對象

 

6、reject方法

reject與resolve方法基本類似,但是要注意一種情況,就是當參數是一個thenable對象時

const thenable = {
  then(resolve, reject) {
    reject('出錯了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})

// true

7、finally方法,finally方法用於指定不管 Promise 對象最后狀態如何,都會執行的操作。該方法是 ES2018 引入標准的。

finally方法的回調函數不接受任何參數,這意味着沒有辦法知道,前面的 Promise 狀態到底是fulfilled還是rejected。這表明,finally方法里面的操作,應該是與狀態無關的,不依賴於 Promise 的執行結果。finally本質上是then方法的特例。

const  p = new Promise((resolve, reject)=>{
    const a = Math.ceil( Math.random() * 10 )
    setTimeout(function(){
        if(a > 5) {
            resolve(a)
        } else {
            reject(a)
        }
    },3000)
})


p.then(res=>{
    console.log(res)
}).catch(err=>{
    console.error(err)    
}).finally(()=>{
   console.log('結束')
})

// 無論是resolve 還是 reject都會 執行 finally

// finally的 polyfill也很簡單

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM