JavaScript 异步函数 async await 介绍
TRAVELLERS DESERT
对于异步处理JavaScript从未如此简单。有一段时间,我们使用了回调。然后,我们使用了承诺。现在,我们使用async…await。接下来我把这种方式代称为异步函数
异步功能
异步函数包含async关键字。您可以在正常的函数声明中使用它:
1 2 3
| async function functionName(arguments){ //做一些异步的事情 }
|
您也可以在箭头功能中使用它。
1 2 3
| const functionName = async(arguments)=> { //做一些异步的事情 }
|
异步函数总是返回promise
1 2 3 4 5
| const getOne = async _ => { return 1 } const promise = getOne() promise.toString() //"[object Promise]"
|
await关键字
await 用于处理处理等待返回的结果,如下图所示
1 2 3 4 5 6 7
| const getOne = async () => { return 1 } getOne().then( value => { console.log(value)// 1 })
|
该await关键字可以等待解决的promise。一旦解决了promise,它就会返回传递给then调用的参数。
1 2 3 4
| const test = async _ => { const one = await getOne() console.log(one)// 1 }
|
处理错误
如果一个promise会导致错误,你可以通过catch调用来处理它,如下所示:
1 2 3 4 5 6
| const getOne = async(success = true)=> { if(success)return 1 throw new Error('Failure!') } getOne(false) .catch(error => console.log(error))//失败!
|
如果要在异步函数中处理错误,则需要使用try/catch。
1 2 3 4 5 6 7 8
| const test = async () => { try { const one = await getOne(false) } catch(error){ console.log(error)//失败! } } test()
|
如果您有多个await关键字,错误处理可能会使代码变得混乱……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const test = async () => { try { const one = await getOne(false) } catch(error){ console.log(error)//失败! } try { const two = await getTwo(false) } catch(error){ console.log(error)//失败! } try { const three = await getThree(false) } catch(error){ console.log(error)//失败! } } test()
|
还有更好的方法。一个总的catch函数
1 2 3 4 5 6 7
| 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
await阻止JavaScript执行下一行代码,直到promise解析完成为止。这可能会导致代码执行速度减慢的意外后果。
为了显示这一点,我们模拟一个promise,创建一个延迟。我们可以创建一个延迟sleep函数。
1 2 3
| const sleep = ms => { return new Promise(resolve => setTimeout(resolve,ms)) }
|
ms是解析前等待的毫秒数。如果您传递1000进入sleep,JavaScript的将等待一秒钟之后解决的Promise。
1 2 3 4 5
| let promiseFun = async()=>{ console.time('now') let slp = await sleep(1000) // 延时1秒 console.timeEnd('now') // 1000.106 ms }
|
用async封装原生ajax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| //async const Ajax = ({ method = 'get', url = '/', data, async = true }) => { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest() xhr.onreadystatechange = () => { if (xhr.readyState === 4 && xhr.status === 200) { let res = JSON.parse(xhr.responseText) resolve(res) } } xhr.open(method, url, async) if (method === 'get') { xhr.send() } if (method === 'post') { let type = typeof data let header if (type === 'string') { header = 'application/x-www-form-urlencoded' } else { header = 'application/json' data = JSON.stringify(data) } xhr.setRequestHeader('Content-type', header) xhr.send(data) } }) }
Ajax.get = (url) => { return Ajax({url}) }
async function use() { let data = await Ajax.get('http://localhost:3000/getData') console.log(data) }
use()
|
小伙伴们也可以用async await 试着封装一下fetch。