了解 async/await 更優雅的非同步處理的解決方案
async/await 是基於 promise 的進一步的一種優化,處理方式更加優雅。
從字面意思上理解async/await:async 是非同步的意識,await 有等待的意思,而兩者的用法上也是如此。async用於宣告乙個非同步的 function,而 await 用於等待乙個非同步方法執行完成。
// promise 示例
function getuserinfo() )
}// async await 基礎示例
async function getuserinfo()
基本規則
async 關鍵字
// async 示例
async function demofn()
demofn().then((res) => )
# async 函式會返回乙個 promise 物件,如果函式中返回的是乙個值,async直接會用promise.resolve()包裹一下返回
表明程式裡面可能有非同步過程:裡面可以有await關鍵字;當然全部是同步**也沒有關係,但是這樣async關鍵字就顯得多餘了;
非阻塞:async函式裡面如果有非同步過程會等待,但是async函式本身會馬上返回,不會阻塞當前執行緒,可以簡單認為,async函式工作在主線程,同步執行,不會阻塞介面渲染,async函式內部由await關鍵字修飾的非同步過程,工作在相應的協程上,會阻塞等待非同步任務的完成再返回。
async函式返回型別為promise物件:這是和普通函式本質上的不同,也是使用時重點注意的地方;
無等待:聯想到promise的特點,在沒有await的情況下執行async函式,會立即執行,返回乙個promise物件,並且絕對不會阻塞後面的語句,這和普通返回promise物件的函式並無二致
await不處理非同步error:await是不管非同步過程的reject(error)訊息的,async函式返回的這個promise物件的catch函式負責統一抓取內部所有非同步過程的錯誤;async函式內部只要有乙個非同步發生過錯誤,整個執行過程就中斷,這個返回的promise物件的catch就能抓取到這個錯誤;
async函式的執行:async函式執行和普通函式一樣,引數個數隨意,沒有限制,也需要有async關鍵字;只是返回值是乙個promise物件,可以用then函式得到返回值,用catch抓取整個流程中發生的錯誤;
await 關鍵字
await只能在async函式內部使用:不能放在普通函式裡面,否則會報錯
await關鍵字後面跟promise物件:在pending狀態時,相應的協程會交出控制權,進入等待狀態,這是協程的本質
await是async await的意識:await的是resolve(data)的訊息,並把資料data返回,比如下面**中,當promise物件由pending變成resolved的時候,變數a就等於data,然後再順序執行下面的語句console.log(a),這真的是等待,真的是順序執行,表現和同步**幾乎一模一樣
const a = await new promise((resolve, reject) => )
console.log(a)
**await後面也可以跟同步**: ** 不過系統會提示將其轉換成乙個promise物件,比如:
const a = await 'hello world!'
// 相當於
const a = await promise.resolve('hello world!')
// 跟同步**是一樣的,還不如省事一點,直接去掉await關鍵字
const a = 'hello world!'
await對於失敗訊息的處理:await只關心非同步過程成功的訊息resolve(data),拿到相應的資料data,至於失敗訊息reject(error),不關心不處理;對於錯誤的處理由以下幾種方法供選擇:
async function mount()
} catch (error)
}
**await對於結果的處理: ** await是個運算子,用於組成表示式,await表示式的運算結果取決於它等的東西,如果它等到的不是乙個promise物件,那麼await表示式的運算結果就是它等到的東西,如果是promise物件,await就忙起來了,會阻塞後面的**,等著promise物件resolve,然後得到resolve的值,作為await表示式的執行結果;雖然是阻塞,但async函式呼叫並不會造成阻塞,它內部所有的阻塞都被封裝在乙個promise物件中非同步執行,這也正是await必須用在async函式中的原因
用 async/await 替換 promise 的不完美 ?
錯誤處理示例
// 定義getjson
function getjson()
# 在以下的promise示例中,try/catch不能處理json。parse的錯誤,因為它在promise中。我們需要使用.catch這樣錯誤處理**非常冗餘。並且,在實際生產**會更加複雜。
function makerequest() )
// 取消注釋,處理非同步**的錯誤
//.catch((err) => )
} catch (error)
}# 使用 async/await 讓 try/catch 可以同事處理同步和非同步錯誤。能處理 json.parse 錯誤; async/await 最讓人舒服的一點是**看起來是同步的
async function makerequest() catch (error)
}
條件語句示例
# 根據返回資料決定是直接返回,還是繼續獲取更多的資料
function makerequest() )
} else
})}// 注意:這種多層巢狀並且 return語句很容易讓人感到迷茫,而它們只是需要將最終結果傳遞到最外層的promise
# 使用 async/await 這才是真正擺脫**地獄的正確做法
async function makerequest() else
}
# 場景分析: 呼叫 promise1,使用 promise1 返回的結果去呼叫 promise2,然後使用兩者的結果去呼叫 promise3
function makerequest() )
})}// 或者
function makerequest() )
.then(([value1, value2]) => )
}// 無論怎麼寫都會覺得複雜,使用async/await,將複雜的場景簡化
async function makerequest()
理解async await的原理
了解過了promise之後,就不得不提乙個東西,那就是async await,async await是乙個很重要的語法糖,他的作用是用同步的方式,執行非同步操作。要實現乙個東西之前,最好是先搞清楚這兩樣東西 一 有什麼用?async await的用處就是 用同步方式,執行非同步操作,怎麼說呢?舉個例...
同步非同步的理解 (async await)
近期在工作中使用同步非同步方法,出現bug,感覺以前對於同步非同步,阻塞非阻塞理解的有問題,於是在網上重新學習 找到以下的回答 同步 執行乙個操作之後,等待結果,然後才繼續執行後續的操作。非同步 執行乙個操作後,可以去執行其他的操作,然後等待通知再回來執行剛才沒執行完的操作。阻塞 程序給cpu傳達乙...
async await函式的執行順序的理解
最近遇到乙個關於async函式使用的bug,因 涉及太多業務,所以模擬了 如下 let testarr 1 2,3 let flag false const func res testarr.foreach async item console.log flag flag 當時寫 的人的目的很簡單,...