1. 程式人生 > >理解promise,實現非同步的同步編寫

理解promise,實現非同步的同步編寫

MND解釋:Promise 物件用於表示一個非同步操作的最終狀態(完成或失敗),以及其返回的值。

我的理解就是promise是一種完成非同步功能並檢查狀態觸發回撥的機制。

1、兩種常用建立方式:

宣告一個變數:(宣告一個promise型別的物件)

const myFirstPromise =newPromise((resolve, reject)=>{// ?做一些非同步操作,最終會呼叫下面兩者之一://   resolve(result); // fulfilled// ?或   reject(error); // rejected});

宣告一個函式:(返回一個promise型別的物件)

functionmyAsyncFunction
(url){returnnewPromise((resolve, reject)=>{const xhr =newXMLHttpRequest(); xhr.open("GET", url); xhr.onload =()=>resolve(xhr.responseText); xhr.onerror =()=>reject(xhr.statusText); xhr.send();});};

顯而易見,如果需要給非同步過程傳遞函式,當然要優先選擇第2種方式了。

2、promise的狀態

promise的中文釋義為承諾,物件如其名,在未來的某一個時刻將會有狀態變化進而有真實的結果。當代碼執行到變數myFirstPromise

或呼叫函式myAsyncFunction時,得到的都應該是一個空值或空物件,同時會有一個new promise()物件被構建。此時的promise物件處於一種名為pending狀態表示為初始狀態。此時promise開始執行。

new promise(/*...code...*/ ) 中的code只是相當於一個引數被傳遞給promise物件,和以往的函式呼叫傳參的不同在於:code是函式型別的引數 (resolve, reject)=>{ } ,不是一個字串、數值等等型別的引數。這個函式型別的引數code只接收resolve、reject兩種型別的引數。code函式體內可以正常使用當前檔案裡的變數引數、函式等等。

promise執行過程中,對我們來說最終的就是這個具有定製意義的code引數,該引數可以是一個XHR請求、setTimeout()函式等等。執行code,如果順利完成,得到我們預期的正確結果,promise物件將處於一種名為fulfilled狀態,表示操作成功完成。執行code,如果未完成,將可以報錯,promise物件將處於一種名為rejected狀態,表示操作失敗。此時我們之前宣告的變數或函式的呼叫將有一個結果:兌現承諾,得到的仍然是之前的promise,只是此時此刻,它有了新的狀態,表明之前的承諾有了結果。

3、promise的回撥

promise狀態從pending改變後,它將觸發(非同步呼叫)相應的函式(如同我們之前常用的回撥函式),這些函式存在於promise的yuanxing裡如then()、catch(),當然還有一個finally()。

myFirstPromise.then(// 記錄填充值function(val){
            console.log('兌現成功的promise', val);}).catch(  // 記錄失敗原因(reason)=>{
            console.log('處理失敗的 promise', reason);});

finally回撥函式:

4、promise的來源

在JavaScript的世界中,所有程式碼都是單執行緒執行的。但如網路操作,瀏覽器事件,都必須是非同步執行。對於需要非同步執行的程式碼,js不會立即去執行,而是把它扔到一個事件佇列裡面,當所有同步任務都幹完了以後,再去遍歷執行事件佇列裡面的程式碼。一個已經變成 resolve 狀態的 promise,傳遞給 then 的函式也總是會被非同步呼叫。

promise替代了下面這種舊式的函式,

functionsuccessCallback(result){
  console.log("It succeeded with "+ result);}functionfailureCallback(error){
  console.log("It failed with "+ error);}doSomething(successCallback, failureCallback);

提供了新式的函式:

const promise =doSomething();promise.then(successCallback, failureCallback);//或者doSomething().then(successCallback).catch(failureCallback);

參考: