Axios -- 簡單易懂Promise

目錄

瞭解Promise

Promiseの鏈式操作及Resolve的用法

Reject的用法

Catch的用法

all的用法

Race的用法

補充


瞭解Promise

Promise :ES6提供的一個構造函數,處理異步事件。接收了一個參數爲函數,傳入resolve,reject兩個參數。resolve爲異步操作成功後執行的回調函數,reject爲異步操作失敗後執行的回調函數。Promise對象上有then,catch方法。例子:

function snycA(){
    const promise = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('執行完成');
            resolve('異步數據1');
        },2000)        

    })
    return promise
}

snycA().then((response)=>{
    console.log(response);
    
})

輸出的結果爲:

                      

Emmmmm...然而這種操作不就跟平時我們使用回調函數(將回調函數作爲參數傳入函數裏,函數裏面嵌套函數,等函數執行完成再去執行嵌套函數,就叫回調函數啦)一樣了嗎?下面的例子就是用回調函數實現上面所實現的效果:

//將callback作爲一個參數傳入函數中,待函數執行完成再執行回調函數
function syncA(callback){
    setTimeout(()=>{
        console.log("執行完成");
        callback('回調數據1');
    },2000)
}

syncA((data)=>{
    console.log(data)
})

輸出的結果爲: 

                

雖然回調函數也能實現同樣的效果,但是,如果callback也是一個異步操作,而且執行完後也需要有相應的回調函數,該怎麼辦呢?總不能再定義一個callback2,然後給callback傳進去吧。而Promise的優勢在於,可以在then方法中繼續寫Promise對象並返回,然後繼續調用then來進行回調操作。  

Promiseの鏈式操作及Resolve的用法

promise能層層簡化多層回調的寫法,而Promise的精髓在於維護狀態,傳遞狀態。下面來簡單實現一下

function syncA(){
   const P = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('執行syncA');
            resolve('syncA-over')
        })
        
   })
   return P;
}
function syncB(){
   const P = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('執行syncB');
            resolve('syncB-over')
        })
        
   })
   return P;
}
function syncC(){
   const P = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('執行syncC');
            resolve('syncC-over')
        })
        
   })
   return P;
}
syncA().then((data)=>{
    console.log(data);
    return syncB();
}).then((data)=>{
    console.log(data);
    return syncC();
}).then((data)=>{
    console.log(data)
})

輸出結果爲:

這樣,每隔兩秒輸入按順序輸出syncA,syncB,syncC中的內容並執行,傳入resolve()的數據在then中也能直接拿到。

Reject的用法

reject的作用就是把Promise的狀態置爲rejected,這樣我們在then中就能捕捉到,然後執行“失敗”情況的回調。看下面的代碼。

//隨機生成一個1-10的數字,當數字小於8時調用reject,在then在輸出
function syncA(){
    const P = new Promise((reslove,reject)=>{
        setTimeout(()=>{
            let num = Math.floor((Math.random * 10)+1)
            if(num>8){
                reslove(num)
            }else{
                reject('小於8')
            }

        })
       
    })
    return P;
}

syncA().then((num)=>{
    console.log(num)
},(data)=>{
    console.log(data)
})

輸出結果爲:

                     

Catch的用法

catch方法與then中的第二個參數一樣,用來指定reject的回調,也就是上面的代碼可以寫成:

syncA().then((num)=>{
    console.log(num)
})
.catch((data)=>{
    console.log(data)
})

catch還有一個重要的作用!!!!當then方法中resolve拋出異常(代碼錯誤)時,也會進入到我們的catch中,將錯誤信息傳入到我們的catch中,代碼繼續往下執行,並不會中斷!與我們的try/catch語句有相同的功能。

all的用法

用Promise.all來執行,all接收一個數組參數,裏面的值最終都算返回Promise對象。這樣,三個異步操作的並行執行的,等到它們都執行完後纔會進到then裏面。那麼,三個異步操作返回的數據哪裏去了呢?都在then裏面呢,all會把所有異步操作的結果放進一個數組中傳給then,就是上面的results。   有了all,你就可以並行執行多個異步操作,並且在一個回調中處理所有的返回數據,是不是很酷?有一個場景是很適合用這個的,一些遊戲類的素材比較多的應用,打開網頁時,預先加載需要用到的各種資源如圖片、flash以及各種靜態文件。所有的都加載完後,我們再進行頁面的初始化。  

function syncA(){
   const P = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('執行syncA');
            resolve('syncA-over')
        })
        
   })
   return P;
}
function syncB(){
   const P = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('執行syncB');
            resolve('syncB-over')
        })
        
   })
   return P;
}
function syncC(){
   const P = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('執行syncC');
            resolve('syncC-over')
        })
        
   })
   return P;
}
Promise
.all([syncA(), syncB(), syncC()])
.then(function(results){
    console.log(results);
})

輸出的結果爲:

                       

Race的用法

race是 【誰跑的快,以誰爲準執行回調函數】

//請求某個圖片資源
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
            resolve(img);
        }
        img.src = 'xxxxxx.jpg';
    });
    return p;
}
 
//延時函數,用於給請求計時
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('圖片請求超時');
        }, 5000);
    });
    return p;
}

Promise.race([requestImg(),timeout()])
       .then((results)=>{
            console.log(results)
        })
       .catch((reason)=>{
            console.log(reason)
        })

requestImg函數會異步請求一張圖片,我把地址寫爲"xxxxxx",所以肯定是無法成功請求到的。timeout函數是一個延時5秒的異步操作。我們把這兩個返回Promise對象的函數放進race,於是他倆就會賽跑,如果5秒之內圖片請求成功了,那麼遍進入then方法,執行正常的流程。如果5秒鐘圖片還未成功返回,那麼timeout就跑贏了,則進入catch,報出“圖片請求超時”的信息。

 

補充

8.19:resolve是不接受多個參數的,如resolve(a,b)的時候,b將會被忽略。應改爲resolve([a,b])&&sync().then([a,b]),下面是微信羣裏分享的網易雲一面題目以及我的答案

function getValue (a, b) {
  const P = new Promise((resolve) => {
    setTimeout(() => {
      resolve([a, b])
    }, 2000)
  })
  return P
}
getValue(1, 2).then(([a, b]) => {
  return a + b
})

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章