本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
关于异步处理问题,ES5的回调让我们陷入回调地狱轮回,后来ES6诞生了Promise(Promise不了解?点这了解)让我们脱离轮回,终于,在ES7更新出async-await让我们更优雅的处理回调问题。今天我们就来解析解析 async-await和Promise有何联系和区别。
asnyc-await
async 函数是使用async关键字声明的函数。 async 函数是[AsyncFunction]构造函数的实例, 并且其中允许使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于[Promise]的异步行为,而无需刻意地链式调用promise。
asnyc
async关键字用于声明异步函数,它可以在函数声明、函数表达式还有箭头函数中使用,方法如下:
1. async function Async(){}
2. let Async = async function(){}
3. let Async = async ()=>{}
在这我们要注意是await 不能够单独出现,其函数前面一定要有 async ,所以在我们使用时 async 和 await 要结合起来一起使用才有意义。
await
当我们使用async 声明了一个异步函数,那么我们就可以在这个异步函数内部使用await关键字。下面我就用几段代码来理解async-await的用法和promise的不同。
我们先来看看asnyc-await怎么用吧!
function getJSON(){
return new Promise((resolve, reject) => {
setTimeout(() =>{
console.log('JSON');
resolve('ok');
},500)
})
}
async function testAsync(){
await getJSON();
console.log('数据拿到了');
}
testAsync()
在上面这段代码中,我们显然可以看出这是一段异步代码,但是这里我们没有用
promise.then 或者回调来解决,我们用的是async-await来解决,下面我来解析解析async-await的用法:首先我们要在在函数testAsync前添加async,接下来我们用异步代码的调用前添加await,这样的话testAsync函数下面的代码等待异步代码先执行。这就是asnyc-await解决异步回调问题的用法。
既然我们已经知道了async-await的用法下面我们再来一段代码,来给promise和asnyc-await两种方法做个比较:
function getJSON() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(2);
resolve(2)
}, 2000);
})
function testAsync() {
return Promise.resolve(2).then(() =>{
getJSON()
})
.then(() =>{
console.log(3);
})
}
testAsync()
//相当于
function getJSON() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(2);
resolve(2)
}, 2000);
})
}
async function testAsync() {
await getJSON()
console.log(3);
}
testAsync()
在上面这段中,我们就可以看出,我们使用
await ,解释器都创建了一个 Promise 对象,把剩下的async函数中的操作都放到 then 回调函数中。async/await 的实现,离不开 Promise 。从字面意思来理解 async 是“异步”的简写, await 是 async await 的简写,可以理解为等待异步执行结束之后再执行。
既然我们看清了async-await和promise的区别,那下面我们就来聊聊async-await的执行顺序:
console.log('start');
async function async1() {
await async2() // 新款浏览器为 await 开辟了特别通道,执行提前了
console.log('async1 end'); // 来到了当前这一次事件循环的微任务序列
}
async function async2() {
console.log('async2 end');
}
async1()
setTimeout(() => {
console.log('setTimeout');
}, 0)
new Promise(resolve => {
console.log('Promise');
resolve()
})
.then(() => {
console.log('promise1');
})
.then(() => {
console.log('promise2');
})
console.log('end');
我们来分析这段代码的打印顺序,首先我们会打印同步代码,所以打印出start,然后我们就好奇了为什么下面一个打印的不是Promise而是async2 end, 明明async2是异步代码,为啥会先打印呢?这是因为浏览器为 await 开辟了特别通道,执行提前了。所以第二个打印的就是async2 end (可以理解为吧async看成同步代码)之后也就自然打印Promise,end等同步代码,接下来就要执行异步代码了,也就依次打印出了async1 end 、promise 、promise2 ,最后打印setTimeout。
结语
这就是我对async-await的解析,我们不难看出,ES7更新出async-await就是简化了promise的写法,将异步回调的处理变得更加简便。