写在前面
之前我写过一篇文章关于JS中如何解决异步代码挂起的问题Js中异步代码挂起怎么解决? - 掘金 (juejin.cn),文中我主要讲了用Promise来解决异步问题,我们知道了可以用then链来解决多层回调问题,但是用then链的话写起来不够优雅,有点不符合原生JS写法的意思,async和await就很好地解决了这个问题,首先用async声明一个异步函数,然后再用await等待异步结果,把以前then链的结果放到直接放在await,非常方便。
async/await是什么?
async/await语法是在2016年时提出的,简单来说async/await是Promise的语法糖,async是异步的意思,await是等待的意思。async function 申明一个函数里面可能有异步代码需要执行,await则可以认为是等待一个异步方法执行完成。
async/await的用法
我们直接来看下面的例子:
let data = {}
function getData1() {
return new Promise((resolve, reject) => {
//异步代码
setTimeout(() => {
data = { name: 'song', age: 20 }
resolve()
}, 1000)
})
}
function getData2() {
return new Promise((resolve, reject) => {
//异步代码
setTimeout(() => {
data = { name: 'uiiy', age: 20 }
resolve()
}, 2000)
})
}
function showData() {
console.log(`我正在展示获取到的数据:${JSON.stringify(data)}`);
}
async function handle() {
await getData1()
await getData2()
showData()
}
handle()
在上面的代码中我们可以看到getData1和getData2两个函数中都有异步代码,我们用async/await来解决的话在函数体内和使用then链解决一样,都需要return出一个Promise。不同的点就在于async新定义了一个异步函数,getData1和getData2两个函数在异步函数里面调用,然后在两个函数前面都加上await。
async/await的特点
async函数调用会返回一个Promise对象。
sync function handle() {
//return new Promise(()=>{})
return 'hello'
}
const res = handle()
console.log(res);
上面代码执行结果为:
await必须写在async函数里面。
这个特点很好理解,async和await是配套使用的,await规定了要写在 async里面。
await会阻塞下一行代码的执行,封装了Promise.then()。
这也很好理解,我们知道需要耗时的代码都是异步代码,await加在了有异步代码的函数前面,一定要等这个函数执行完毕了才会执行下面的代码,要不然就解决不了异步代码挂起的问题了。
await也会返回出一个Promise对象。
//await
function await() {
return Promise.resolve().then(() => {
})
}
一道面试题
将下面代码async/await翻译成Promise
function getJson() {
return new Promise((resolve, reject) => {
setTimeout(function () {
console.log(2);
resolve(2)
}, 2000)
})
}
async function testAsync() {
await getJson()
console.log(3);
}
testAsync()
我们可以根据async/await的特点翻译成下面的代码:
//翻译成Promise.then执行
function testAsync() {
return Promise.resolve().then(() => {
return getJson()
}).then(() => {
console.log(3);
})
}
变化
如果题目中getJson函数里面没有返回一个Promise对象上面代码的执行结果会改变吗?
function getJson() {
setTimeout(function () {
console.log(2);
resolve(2)
}, 2000)
}
这里显然是会的,这样这个函数里面的异步代码将会挂起,先是输出3,再输出2。
注意:
then也会返回一个Promise对象
async/await的优点——和Promise比较
- 同步代码编写方式,能处理由多个
Promise组成的then链,async/await从上到下,顺序执行,更符合我们的编写习惯。 - 同步代码和异步代码可以一起编写,用
Promise最好将同步代码和异步代码放在不同的then节点中,这样结构更加清晰,而用async/await整个书写习惯都是同步的,不需要纠结同步和异步的区别。 - 语法简洁清晰,节省了很多不必要的匿名函数。
- 减少不必要的中间变量,更清晰明确的错误堆栈。
async/await的局限
- 降低了我们阅读理解代码的速度,此前看到
.then()就知道是异步,现在需要识别async和await关键字。
可以看出,
async/await的优势大部分都是从开发调试效率提升层面来讲的,提到的局限也只有不痛不痒的,所以说async/await整体还是优雅的。
最后
async/await 相比于Promise是更优越的异步处理方案,但我们相信这一定不是终极处理方案。随着前端工程化的深入,一定有更多、更复杂、更精细的异步问题出现,同时也会有迎合这些问题的解决方案出现。最后感谢各位的观看,我们下篇文章见~