異步的JavaScript
從未如何簡單!過去段時間,咱們使用回調。而後,咱們使用promises
。如今,咱們有了異步功能函數。javascript
異步函數可以使得(咱們)編寫異步JavaScript更加容易,可是,它自帶一套陷阱,對初學者很不友好。java
在這個由兩部分組成的文章中,我想分享下你須要瞭解的有關異步函數的內容。【PS:另外一部分暫不打算翻譯】git
異步功能函數包含async
關鍵詞。你能夠在正常的函數聲明中使用它:github
async function functionName (arguments) {
// Do something asynchronous
}
複製代碼
你也能夠使用箭頭函數。數組
const functionName = async (arguments) => {
// Do something asynchronous
}
複製代碼
(異步函數)它無論你返回什麼。其返回值都是promise
。promise
const getOne = async _ => {
return 1
}
const promise = getOne()
console.log(promise) // Promise
複製代碼
筆記:在接着往前讀以前,你應該知道什麼是JavaScript Promises知識點,以及如何使用它們。不然,它會開始變得混亂。這篇文章會幫助你熟悉JavaScript Promise。異步
當你調用promise
時,你會在then
中處理下一步,以下:async
const getOne = async _ => {
return 1
}
getOne()
.then(value => {
console.log(value) // 1
})
複製代碼
await
關鍵字容許你等待promise去解析。一旦解析完promise,它就會返回參數傳遞給then
調用。函數
const test = async _ => {
const one = await getOne()
console.log(one) // 1
}
test()
複製代碼
在返回承諾(promise)以前沒有必要等待(await)。你能夠直接退回承諾。post
若是你
return await
些內容,則你首先是解決了原先promise。而後,你從已經解析的內容(resolved value)建立新的promise。return await
真的沒作什麼有效的東西。無需額外的步驟。
// Don't need to do this
const test = async _ => {
return await getOne()
}
test()
.then(value => {
console.log(value) // 1
})
複製代碼
// Do this instead
const test = async _ => {
return getOne()
}
test()
.then(value => {
console.log(value) // 1
})
複製代碼
注意:若是你不須要
await
,則不須要使用異步功能(async function)。上面的例子能夠改寫以下:
// Do this instead
const test = _ => {
return getOne()
}
test()
.then(value => {
console.log(value) // 1
})
複製代碼
若是一個promise出錯了,你能夠使用catch調用來處理它,以下所示:
const getOne = async (success = true) => {
if (success) return 1
throw new Error('Failure!')
}
getOne(false)
.catch(error => console.log(error)) // Failure!
複製代碼
若是你想在一個異步函數中處理錯誤,你須要調用try/catch
。
const test = async _ => {
try {
const one = await getOne(false)
} catch (error) {
console.log(error) // Failure!
}
}
test()
複製代碼
若是你有多個await
關鍵字,錯誤處理可能變得很難看...
const test = async _ => {
try {
const one = await getOne(false)
} catch (error) {
console.log(error) // Failure!
}
try {
const two = await getTwo(false)
} catch (error) {
console.log(error) // Failure!
}
try {
const three = await getThree(false)
} catch (error) {
console.log(error) // Failure!
}
}
test()
複製代碼
還有更好的方法。
咱們知道異步函數老是返回一個promise。當咱們調用promise時,咱們能夠在catch
調用中處理錯誤。這意味着咱們能夠經過添加.catch
來處理異步函數中的任何錯誤。
const test = async _ => {
const one = await getOne(false)
const two = await getTwo(false)
const three = await getThree(false)
}
test()
.catch(error => console.log(error)))
複製代碼
注意:Promise的
catch
方法只容許你捕獲一個錯誤。
await
阻止JavaScript執行下一行代碼,直到promise解析爲止。這可能會致使代碼執行速度減慢的意外效果。
爲了實際演示這點,咱們須要在解析promise以前建立一個延遲。咱們能夠使用sleep
功能來建立延遲。
const sleep = ms => {
return new Promise(resolve => setTimeout(resolve, ms))
}
複製代碼
ms
是解析前等待的毫秒數。若是你傳入1000
到sleep
函數,JavaScript將等待一秒才能解析promise。
// Using Sleep
console.log('Now')
sleep(1000)
.then(v => {
console.log('After one second')
})
複製代碼
假設getOne
須要一秒來解析。爲了建立這個延遲,咱們將1000
(一秒)傳入到sleep
。一秒事後,sleep
promise解析後,咱們返回值1。
const getOne = _ => {
return sleep(1000).then(v => 1)
}
複製代碼
若是你使用await getOne()
,你會發如今getOne
解析以前須要一秒鐘。
const test = async _ => {
console.log('Now')
const one = await getOne()
console.log(one)
}
test()
複製代碼
如今,假設你須要處理三個promises。每一個promise都有一秒鐘的延遲。
const getOne = _ => {
return sleep(1000).then(v => 1)
}
const getTwo = _ => {
return sleep(1000).then(v => 2)
}
const getThree = _ => {
return sleep(1000).then(v => 3)
}
複製代碼
若是你連續await
這三個promises,你將要等待三秒才能解析完全部promises。這並很差,由於咱們強迫JavaScript在作咱們須要作的事情以前等待了兩秒鐘。
const test = async _ => {
const one = await getOne()
console.log(one)
const two = await getTwo()
console.log(two)
const three = await getThree()
console.log(three)
console.log('Done')
}
test()
複製代碼
若是getOne
,getTwo
和getThree
能夠同時獲取,你將節省兩秒鐘。你能夠使用Promise.all
同時獲取這三個promises。
有三個步驟:
Promise.all
來await
promises數組以下所示:
const test = async _ => {
const promises = [getOne(), getTwo(), getThree()]
console.log('Now')
const [one, two, three] = await Promise.all(promises)
console.log(one)
console.log(two)
console.log(three)
console.log('Done')
}
test()
複製代碼
這就是你須要瞭解的基本異步功能函數!我但願這篇文章爲你掃除了些障礙。
筆記:這篇文章是Learn JavaScript的修改摘錄。若是你發現本文有用,你可能須要去查看它。
至此,系列文callbacks,promises和async/await共三篇文章已經完成~