Async/await
Async functions
async 被放置在一个函数前面:
async function a{ return 1 }
函数前面的async一词意味着一个简单的事情:这个函数总是返回一个promise,如果代码中有return <非promise>语句,JavaScript会自动把返回的这个value值包装成promise的resolved值。
例如,上面的代码返回resolved值为1的promise,我们可以测试一下
async function f() { return 1 } f().then(alert) // 1
我们也可以显式的返回一个promise,这个将会是同样的结果:
async function f() { return Promise.resolve(1) } f().then(alert) // 1
所以,async确保了函数返回一个promise,即使其中包含非promise。够简单了吧?但是不仅仅只是如此,还有另一个关键词await,只能在async函数里使用,
Await
// 只能在async函数内部使用
let value = await promise
关键词await可以让JavaScript进行等待,直到一个promise执行并返回它的结果,JavaScript才会继续往下执行。
以下是一个promise在1s之后resolve的例子:
async function f() { let promise = new Promise((resolve, reject) => { setTimeout(() => resolve('done!'), 1000) }) let result = await promise // 直到promise返回一个resolve值(*) alert(result) // 'done!' } f()
函数执行到(*)行会‘暂停’,当promise处理完成后重新恢复运行, resolve的值成了最终的result,所以上面的代码会在1s后输出'done!'
注意事项
await字面上使得JavaScript等待,直到promise处理完成,然后将结果继续下去。这并不会花费任何的cpu资源,因为引擎能够同时做其他工作:执行其他脚本,处理事件等等。不能在常规函数里使用await如果我们试图在非async函数里使用await,就会出现一个语法错误:
function f() { let promise = Promise.resolve(1) let result = await promise // syntax error }
如果我们忘记了在函数之前放置async,我们就会得到这样一个错误。如上所述,await只能在async函数中工作。
错误处理
如果一个promise正常resolve,那么await返回这个结果,但是在reject的情况下会抛出一个错误,就好像在那一行有一个throw语句一样。
async function f() { await Promise.reject(new Error('whoops!')) }
和下面一样
async function f() { throw new Error('Whoops!') }
在真实的使用场景中,promise在reject抛出错误之前可能需要一段时间,所以await将会等待,然后才抛出一个错误。我们可以使用try-catch语句捕获错误,就像在正常抛出中处理异常一样:
async function f() { try { let response = await fetch('http://no-such-url') } catch (err) { alet(err) // TypeError: failed to fetch } }
如果发生了一个错误,控制会跳转到catch块。当然我们也能够捕获多行语句:
async function f() { try { let response = await fetch('/no-user-here') let user = await response.json() } catch(err) { // 在fetch和response.json中都能捕获错误 alert(err) } } f()
总结
放在一个函数前的async有两个作用:1.使函数总是返回一个promise2.允许在这其中使用await
promise前面的await关键字能够使JavaScript等待,直到promise处理结束。然后:1.如果它是一个错误,异常就产生了,就像在那个地方调用了throw error一样。2.否则,它会返回一个结果,我们可以将它分配给一个值
有了async/await,我们很少需要写promise.then/catch
最后将代码奉上:可自己运行学习
<template> <div class="asyncawait"> <h1>Async/Await</h1> <Button type="primary" @click="handleClick">调用</Button> </div> </template> <script> export default { name: 'async-await', props: {}, data () { return {} }, watch: {}, computed: {}, components: {}, mounted () { this.initFun (); }, methods: { async func () { return 1 }, handleClick () { // console.log(this.func()) this.func ().then (res => { console.log (res) }); this.testResult (); }, async initFun () { let promise = new Promise ((resolve, reject) => { setTimeout (() => resolve ('done!'), 3000) }); console.log (333333333); let result = await promise; console.log (1111111111); }, doubleAfter2seconds (num) { return new Promise ((resolve, reject) => { setTimeout (() => { resolve (num) }) }) }, async testResult () { try { let third = await this.doubleAfter2seconds ('阿') let second = await this.doubleAfter2seconds ('好'); let first = await this.doubleAfter2seconds ('你'); console.log (first + second + third); } catch (err) { throw new Error ('askdfjaskdfjla'); } } } } </script> <style lang="less" scoped> .asyncawait { text-align: center; } </style>
交流
我是老礼,公众号「进军全栈攻城狮」作者 ,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!