async/await是一種編寫異步代碼的新方法,以前編寫異步代碼的方案是回調和promisehtml
async/await其實是創建在promise的基礎上,它不能與普通回調或者node回調一塊兒用node
async/await像promise同樣,也是非阻塞的promise
async/await讓異步代碼看起來、表現起來更像同步代碼,這正是其威力所在異步
假設函數getJSON
返回一個promise
,而該promise
的完成值是一個JSON對象,咱們只想調用它,並輸出該JSON,而後返回「done」async
promise的實現函數
const makeRequest = ()=>{ getJSON().then( data => { console.log(data) return "done" } ) } makeRequest()
async、await的實現調試
const makeRequest = async ()=>{ console.log(await get.JSON()) return "down" } makeRequest()
async、await與Promise的區別code
函數前面有一個關鍵字 async。await 關鍵字只用在用 async 定義的函數內。全部 async 函數都會隱式返回一個 promise,而 promise 的完成值將是函數的返回值(本例中是 "done")。htm
上面一點暗示咱們不能在代碼的頂層用 await,由於這樣就不是在 async 函數內。對象
await getJSON() 意味着 console.log 調用會一直等待,直到 getJSON() promise 完成並打印出它的值。
咱們沒必要寫 .then,建立一個匿名函數來處理響應,或者給不須要用的變量一個名稱 data。咱們還避免了代碼嵌套。這些小小的優點會快速累積起來,在後面的代碼中會變得更明顯。
async/await 會最終讓咱們用一樣的結構( try/catch)處理同步和異步代碼變成可能。在下面使用 promise 的示例中,若是 JSON.parse 失敗的話,try/catch 就不會處理,由於它是發生在一個 prmoise 中。咱們須要在 promise 上調用 .catch,而且重複錯誤處理代碼。這種錯誤處理代碼會比可用於生產的代碼中的 console.log 更復雜。
const makeRequest = () => { try { getJSON().then( result => { // 這裏發生錯誤 const data = JSON.parse(result) console.log(data) }).catch((error)=>{ console.log(error) }) } catch (err) { // 這裏不會捕捉到err console.log(err) } }
如今看看用 async/await 實現的代碼。如今 catch 塊會處理解析錯誤。
const makeRequest = async () => { try { // 這個解析會失敗 const data = JSON.parse(await getJSON()) console.log(data) } catch (err) { console.log(err) } }
假設想作像下面的代碼同樣的事情,獲取一些數據,並決定是否應該返回該數據,或者根據數據中的某些值獲取更多的細節。
const makeRequest = () => { return getJSON() .then(data => { if (data.needsAnotherRequest) { return makeAnotherRequest(data) .then(moreData => { console.log(moreData) return moreData }) } else { console.log(data) return data } }) }
這些代碼看着就讓人頭疼。它只需將最終結果傳播到主 promise,卻很容易讓咱們迷失在嵌套( 6 層)、大括號和返回語句中。
把這個示例用async / await 重寫,就變得更易於閱讀。
const makeRequest = async () => { const data = await getJSON() if (data.needsAnotherRequest) { const moreData = await makeAnotherRequest(data); console.log(moreData) return moreData } else { console.log(data) return data } }
你可能發現本身處於一種狀態,即調用你 promise1,而後用它的返回值來調用promise2,而後使用這兩個 promise 的結果來調用 promise3。你的代碼極可能看起來像這樣:
const makeRequest = () => { return promise1() .then(value1 => { // do something return promise2(value1) .then(value2 => { // do something return promise3(value1, value2) }) }) }
不過用 async/await 的話,一樣的邏輯就變得超級簡單直觀了。
const makeRequest = async () => { const value1 = await promise1() const value2 = await promise2(value1) return promise3(value1, value2) }
最後可是一樣重要的是,在使用 async/await 時,一個殺手級優點是調試更容易。調試 promise 一直是如此痛苦,有兩個緣由:
無法在返回表達式(無函數體)的箭頭函數中設置斷點。
const makeRequest = () =>{ return callAllPromise() .then(()=> callAllPromise()) .then(()=> callAllPromise()) .then(()=> callAllPromise()) .then(()=> callAllPromise()) }
若是在.then塊中設置斷點,並使用像單步調試這類調試快捷方式,調試器不會移動到後面的 .then ,由於它只單步調試同步代碼。
有了 async/await,咱們就再也不須要那麼多箭頭函數,您能夠像正常的同步調用同樣單步調試 await 調用。
const makeRequest = async ()=>{ await callAllPromise() await callAllPromise() await callAllPromise() await callAllPromise() }