async作为一个关键字放在函数前面,表明这是一个异步函数。await,等待,后面可以跟任何表达式,但一般跟一个返回promise对象的表达式。await关键字必须放在async函数里面。
async函数的返回值
- 如果async函数中有返回值,会调用Promise.resolve()包装后作为返回值。
- 如果返回值恰好是一个promise对象,则会返回一个pending状态的promise对象。
- 如果函数中没有返回值,则返回Promise.resolve(undefined)。
- 如果函数中有await或其他异步语句,函数没执行完,怎么知道有没有返回值呢,所有返回一个pending状态的promise对象。
- 如果函数内部抛出错误,则会调用Promise.reject()返回一个promise对象。
async function test() {
return 'hello'
}
async function test1() {
return Promise.resolve('world')
}
async function test2() {
let a = 2
await ++a
return a
}
async function resu() {
let res = test()
let res1 = test1()
let res2 = test2()
console.log(res)
console.log(res1)
console.log(res2)
}
resu()
结果:
加了await的返回值
async function test() {
return 'hello'
}
async function test1() {
return Promise.resolve('world')
}
async function test2() {
let a = 2
await ++a
return a
}
async function resu() {
let res = await test()
let res1 = await test1()
let res2 = await test2()
console.log(res)
console.log(res1)
console.log(res2)
}
resu()
相对于上面那个例子,只是加了个await。查看结果:
这个怎么理解呢?
因为赋值语句是立即执行的,async函数虽然可能里面都是同步语句,但这个函数是异步的,所有语句执行完后,你可以当做这个函数没有执行完,所以赋值的是一个promise对象。加上await之后,等待异步函数执行完之后,再执行赋值语句,该返回啥就返回啥嘛。
我们不使用await,在async函数执行完之后,再进行赋值语句,看等于啥。
async function test() {
return 'thanks'
}
let a = test()
console.log(a)
new Promise((resolve, reject) => {
resolve(test())
}).then(b => {
console.log(b)
})
我们来看看结果:
历史总是惊人的相似!
async await执行顺序——让出线程?
await后面如果接的是同步语句,则会立即执行,然后让出当前线程;await后面如果接的是异步语句,则会将其加入队列,然后让出当前线程。
但是让出线程后,什么时候回来执行后面的代码呢?-_- !
先让我们看一个例子:
async function test1() {
await console.log('test1')
console.log(111)
}
async function test2() {
await Promise.resolve().then(() => {
console.log('test2')
})
console.log(222)
}
async function test3() {
await setTimeout(() => {
console.log('test3')
}, 0)
console.log(333)
}
setTimeout(() => {
console.log('宏任务开始')
}, 0)
Promise.resolve().then(() => {
console.log('微任务开始')
})
test1()
test2()
test2()
test3()
Promise.resolve().then(() => {
console.log('微任务结束')
})
setTimeout(() => {
console.log('宏任务结束')
}, 0)
结果:
可以看到,await后面跟一个setTimeout()并没有什么作用。所有还是开头那句话,await后面一般跟一个可以返回promise对象的表达式。如果await后面跟的是一个可以返回promise对象的表达式,则会等它执行完后,再将后面的代码加入到微任务中;否则,立即将后面的代码加入到微任务中。
await后面的promise对象状态可能是rejected,所以最好把await放在try…catch中。
async function test() {
try {
await dosomething()
} catch (err) {
console.log(err)
}
}
test().then(f1, f2)