async await关键字是ES7的一部分,async定义在函数声明之前,使函数变成异步函数,其返回一个Promise对象;await关键字用于等待一个Promise对象,它只能在async函数中才起作用。通过使用它们,让异步代码看起来更像是老式同步代码。
Promise是ECMAscript6原生提供的对象。Promise对象代表了未来将要发生的事件,用来传递异步操作的消息。具体详情见runoob的Promise介绍
async/await的使用
- async函数返回一个promise对象,可以使用then方法添加回调函数
async function test(){
return '张三'
}
// async返回的是一个promise对象,如果async函数没有返回值,async函数返回一个undefined的promise对象
test().then(res=>{
console.log(res);//张三
})
- 当函数执行的时候,一旦遇到await就会返回,等到异步操作完成,再接着执行函数体内后面的语句
async function test(){
return '张三'
}
async function test1() {
let a = await test()
console.log(a)
}
test1() // 张三
async、await执行顺序
- await后面的函数执行完毕时,await会产生一个微任务(promise.then是微任务),执行完await之后,直接跳出async函数,执行其他代码。
console.log('script start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve =>{
console.log('Promise')
resolve()
}).then(function(){
console.log('Promise1')
})
// script start => async2 end => Promise => async1 end => promise1 => setTimeout
区别
- 异常处理:Promise对象中提供catch方法对异常处理。async在异常处理中通过try{}catch(){}处理。
function test(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (a === 1) {
resolve(2)
} else {
reject(3)
}
}, 1)
})
}
// promise 异常处理
function test1(a) {
test(a).then(e => {
console.log(e)
}).catch(e => {
console.log(e)
})
}
test1(1) // 2
test1(2) // 3
// async/await 异常处理
async function test2(a) {
try {
let b = await test(a)
console.log('b', b)
} catch(e) {
console.log('e', e)
}
}
test2(1) // b 2
test2(2) // e 3
- 代码结构上async/await更接近与同步的写法。promise中引入then、catch的方法,代码更显冗余。
- async/await结合中,大量的await的promises相继发生会使程序变慢
function test(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (a === 1) {
resolve(2)
} else {
reject(3)
}
}, 1)
})
}
function testPromise() {
let i = 0, arr = []
for (; i < 20; i++) {
arr.push(test())
}
return Promise.all(arr)
}
async function testAsync() {
let i = 0
for (; i < 20; i++) {
await test()
}
return null
}
let time = console.time()
testPromise().then(e => {
console.timeEnd(time) // 3ms
})
setTimeout(() => {
let time1 = console.time()
testAsync().then(e => {
console.timeEnd(time1) // 89ms
})
}, 0)
总结
async和promise都是异步方法,区别是async生成的结果是promise对象,async是promise的终结版。await只能在async中使用,await是阻塞的意思,就是暂停,你一起调用2个接口,第一个执行完,不输出结果,要等第二个接口执行完,才返回这两个的结果。
使用async/await并不需要回调嵌套,也不需要写多个then方法,在使用上甚至类似一个同步操作。