本質緣由是JS須要交互,須要引入時間的概念。web
sync=同步,async=不一樣步,字面意思跟實際執行狀況正好相反。若是沒有異步執行,則按照JS的代碼一條一條line by line同步執行,執行的邏輯是event loop,即每條代碼執行過程當中:若是在main thread上的代碼則逐步執行,同步執行順序參考: developer.mozilla.org/en-US/docs/… 優先級**(stack/script,microtask/promise,task/webapi)**api
若是要在執行中引入前後的順序怎麼辦?好比先獲取地理位置再才能計算距離長度。若是同步執行,則會發生錯亂。好比地理位置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
須要注意的細節是: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)
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/…