關於promise和async的深刻理解

  1. 本質緣由是JS須要交互,須要引入時間的概念。web

  2. sync=同步,async=不一樣步,字面意思跟實際執行狀況正好相反。若是沒有異步執行,則按照JS的代碼一條一條line by line同步執行,執行的邏輯是event loop,即每條代碼執行過程當中:若是在main thread上的代碼則逐步執行,同步執行順序參考: developer.mozilla.org/en-US/docs/… 優先級**(stack/script,microtask/promise,task/webapi)**api

  1. 既然JS正常是同步執行,爲什麼要引入異步的概念?異步的引入是爲了「同步」操做流程!

若是要在執行中引入前後的順序怎麼辦?好比先獲取地理位置再才能計算距離長度。若是同步執行,則會發生錯亂。好比地理位置api尚未返回回來,則開始了計算,會出現undefined的錯誤。promise

let location=getLoaction(api){
    fetch(api);
}
//calCulateDistance
let distance= (location+32)*232/45;
console.log(distance);
複製代碼

那麼該怎麼「同步」這些前後順序的操做呢?即經過人工控制執行順序。bash

#一. 以CallBack方法引入前後順序#異步

fetch(api,(err,location)={
    if(location) {
      let distance= (location+32)*232/45;
      console.log(distance);
    };
})
複製代碼

問題是:複雜的邏輯,會引發callback hell,並且把callback函數交由第三方fetch很差。async

#二. 以Promise方法引入前後順序(須要改寫CallBack)函數

getLoaction ()=>{
 return new Promise((resolve, reject) =>{  
    fetch(api,(err,location)={
    if(location) {
     resolve(location)
    }else{
     reject(err)
    };
})
})

複製代碼

須要仔細理解的是:代碼行碰到promise的時候即開始執行(按照原生的自帶的順序執行stack/microtask/task),輪到microtask的時候,promise已經開始執行,promise是一個已經存在的對象object,這個對象狀態在按照內部邏輯更新而已,即pending->fullfilled(reject/resolve)。這個對象是一直存在的。這個對象的內部有一些監聽器,then/catch,當對象狀態變化時,則觸發onThen監聽器,其實也是調用咱們傳入的CallBack函數而已!這樣說來promise本質是方法一CallBack的不一樣寫法而已!!oop

須要注意的細節是:

  1. Promise的狀態在microtask完成後才能改變,若是要獲取改變後的值,則須要then,否則promise只是一個帶狀態的object

  1. 若是修改一下,則發現以下結果,由於microtask運行按照queue來的

3.關於then(其實就是CallBack函數,也叫then handler)返回的問題fetch

A.若是then返回return了ThenReturnedValue,則至關於返回一個Promise.resolve(),這個promise以供下一個then來使用consumeui

B.若是then返回了reject或者throw error,則Promise.reject()

C.若是then返回一個新的Promise,叫NewPromise,則NewPromise

then由於是CallBack,error first callback(實際上是error second callback),因此形式是:.then( resolveCallBackFun,rejectCallBackFun)

#三. 以Async Await方法引入前後順序(改寫Promise)

  1. Async實際上是promise+generator(本質是promise), await就是至關於把promise .then了一下(固然error是經過try catch獲取,相似then/catch),跟promise區別是會把後面的所有暫停住,至關於wrap到then裏面。如圖
function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 1000);
  });
}

async function asyncCall() {
  console.log('calling');
  var result = await resolveAfter2Seconds();
  console.log(result);
  console.log('ending');
 }


function promiseCall2() {
  console.log('calling');
  resolveAfter2Seconds().then((result)=>{
     console.log(result);
   }); 
  console.log('ending');
}

asyncCall();//會hold住全部後面的;整個執行順序仍是正常同步流程stack->microtask->task
> "calling"
> "resolved"
> "ending"

promiseCall2(); //只會hold then裏面的;整個執行順序仍是正常同步流程stack->microtask->task
> "calling"
> "ending"
> "resolved"
複製代碼

2.關於async函數func返回的問題, 至關於.then callback, async函數返回也:

A.若是返回value,則async返回Promise.resolve()

B.若是返回NewPromise,則NewPromise

C.若是返回Error,則Promise.reject(),能夠經過後續的try/catch捕獲

D.若是沒有return,則返回Promise.resolve(NULL)

3.async的小技巧IIF

(async () => {
    try {
        var text = await myPromise();
         
    } catch (e) {
       
    }
})();

複製代碼

上面的論證被Mozilla再次證實!

重要文獻:

jakearchibald.com/2015/tasks-…

developer.mozilla.org/en-US/docs/…

developer.mozilla.org/en-US/docs/…

developer.mozilla.org/en-US/docs/…

相關文章
相關標籤/搜索