async和await 是es6新增的关键字,用于把异步变同步;
async在函数定义时使用,用async定义的函数默认返回一个Promise实例,可以直接.then(async还可以定义对象的方法),如果async定义的函数执行返回的不是一个promise对象,那么就会给返回值包装成一个promise对象(将返回值放进promise实例的resolve方法中当做参数)
await (要和async一起使用,一般是在async声明的函数中使用)
await 会等待,等它右侧的代码执行完;
用法
1. 如果await右侧是同步的代码,就会让同步代码执行;如果执行的是一个函数,还会把函数的返回值给到await左边的变量
let p;
async function f3() {
p = await 18;
console.log(p);
}
f3();
console.log(1);
console.log(p);
// 结果是1,undefined,18
js执行的时候是从右向左执行的,先执行18然后遇到await会将await左边的连同下面的都放进微任务中去,所以外面的p打印会是undefined,然后同步代码执行完再执行微任务的时候将其执行,给p赋值,打印p.
2. 如果await右侧是一个Promise实例,或者一个方法返回了Promise实例,await会等着Promise的实例resolve,并且在实例resolve之前,await后面的代码不执行;并且还会拿到Promise在resolve时传入的值,并且赋值给等号左侧变量;
async function f(){
return 10;
}
async function f3() {
let p = await f();
console.log(p);
}
f3();
console.log(1);
// 1,10
上面说了async定义的函数后面如果返回的不是一个promise对象而是一个普通值就会默认包装成一个promise对象,并将其返回值赋值给await左边的变量,如果我们不使用async而是写一个promise对象,如下:
function f(){
return new Promise(((resolve, reject) => {
resolve(10);
}))
}
async function f3() {
let p = await f();
console.log(p);
}
f3();
console.log(1);
// 会发现打印的依旧是1,10
3. await会把await下面的代码变成微任务;上面代码就能看出来,先打印1再打印10,就是因为await将下面的代码当做一个微任务整体放进了等待任务队列中
async和await就是promise的语法糖,封装了promise的then链式调用的繁琐以及处理回调的杂乱,让我们更简单更方便的使用promise来管理我们的异步代码
例如
我们有a,b,c三个异步操作,要求b依赖于a的返回值,c依赖于b的返回值
使用promise 链式调用
function a() {
return new Promise(((resolve, reject) => {
setTimeout(()=>{
resolve(1);
},1000)
}))
}
function b(result) {
return new Promise(((resolve, reject) => {
setTimeout(()=>{
console.log(result);
resolve(2);
},2000)
}))
}
function c(result) {
return new Promise(((resolve, reject) => {
setTimeout(()=>{
console.log(result);
resolve(3);
},3000)
}))
}
let aP=a();
aP.then(b).then(c);
使用async和await
function a() {
return new Promise(((resolve, reject) => {
setTimeout(()=>{
resolve(1);
},1000)
}))
}
function b(result) {
return new Promise(((resolve, reject) => {
setTimeout(()=>{
console.log(result);
resolve(2);
},2000)
}))
}
function c(result) {
return new Promise(((resolve, reject) => {
setTimeout(()=>{
console.log(result);
resolve(3);
},3000)
}))
}
async function f() {
let aP = await a();
let bP = await b(aP);
let cP = await c(bP);
}
f();
经典的面试题
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
async1();
new Promise(function (resolve) {
console.log('promise1')
resolve();
}).then(function () {
console.log('promise2')
})
console.log('script end');