async和await是为了解决异步操作而提出来的规范,在ES7已经实现了,可以让代码看起来更加像同步代码。
下面总结几个知识点:
1.直接调用async函数返回的是一个promise对象
2.await在等待的是后面的返回值 如果是promise的话,那就会等待最后resolve的值然后返回,如果是普通值就直接返回
3.async适用于有依赖关系的异步操作,比如a异步操作返回值为x,后面要用到x,这样就比较合适,如果没有依赖,用Promise.all方法会更好。有依赖的时候,前面的值可以随时在后头使用,这个是then无法比拟的优势,因为可以一直拿,而then在回调函数里头写的参数,没有这里await看起来更直观
4.async函数内部其实是会发生阻塞的,await那部分,会返回值也就是resolve的值,后面的相当于是then放在了微任务里头
async function fun2() {
...
}
async function find() {
let s = await fun2()
}
find()
await其实是在等后头的返回值,其实是then的语法糖,是想拿到resolve的值,后头的代码都会被阻塞住,也就是在async函数find里头执行fun2()后头的代码全部都会阻塞,因此会花费很多时间。来看一道面试题,里头结合了这些异步的打印顺序问题。
async function async1(){
console.log('1')
await async2()
console.log('2')
}
async function async2(){
console.log('3')
}
console.log('4')
setTimeout(function(){
console.log('5')
},0)
async1();
new Promise(function(resolve){
console.log('6')
resolve();
}).then(function(){
console.log('7')
})
console.log('8')
打印结果是41368275,在async1里头,执行async2的时候,阻塞住了,后头的可以理解为then后头的了,可以知道then就是微任务,因此在微任务的第一个,所以结果就是这样了。
接下来再举一个例子,说明async和await的本质
function fn1() {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(1)
},5000)
})
}
function fn2() {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(2)
},1000)
})
}
async function test() {
let s = await fn1()
console.log('test函数里头的同步代码')
console.log(s);
let s2 = await fn2();
console.log(s2)
}
//相当于是fn1().then(s => {
// let s = s;
// console.log('test函数里头的同步代码')
// console.log(s);
// fn2().then(s2 => {
// console.log(s2)
// })
//});
其实,就是把await函数后头的内容给放在了fullfillCackbacks里头,因此不会阻塞,async函数后头的代码运行,异步完成了之后,就会完成后头的代码
var x = test();
console.log(x);
console.log('test后头的同步代码')
首先,这里头的fn1和fn2都可以看成是async函数,因为都返回的是一个promise对象,也是就是说,如果加上async的话,就不用手动去写return new Promise这行代码了,他会自动帮我们包裹处理一下。
所以可以总结async函数和await的本质了,直接调用async函数的时候,返回的是整个 大的promise对象,而async里头的代码都是这个大的promise对象的executor同步代码,会立即执行,执行executor函数的时候,是因为fn1是返回的promise,而且还是pending态的,这个await相当于就分隔开了async函数内部的代码段,await就是then的语法糖,fn1之后,拿到resolve的值然后给s,但是因为是pending,所以加入到了fullfillcackbacks里头等待resolve的时候去回调即可,后头的await也是同理。
所以async函数里头的代码其实和promise是一样的原理,then里头的东西加到了fullfillcallbacks里头,因此后头的代码是不会被阻塞的。