介绍
async 和 await结合可以以同步代码编程方式书写异步代码。
async函数的隐式返回值是Promise(许诺)对象。(见es6 promise)
await表达式:
- await必须写在async函数中。
- await右边的表达式必须是promise对象。
- await返回的是promise成功的值,失败时抛出异常。
原理
async/await的使用是把函数暂停了,当执行到await时,函数暂停执行,直到await等待的Promise状态改变时回到这个函数执行。
协程
协程是跑在线程上的任务,一个线程上可以有多个协程,但是一个线程同时只能执行一个协程。
生成器
前面带有关键字的一个函数可以暂停执行或者恢复执行。在函数内部可以使用yield关键字来暂停函数的执行,切换到外部函数,其实就是协程的切换。在外部函数中可以通过调用next()方法来恢复函数的执行。
async/await原理
async隐式返回Promise对象
代码执行梳理
async function foo() {
console.log(1);
const result = await new Promse((reslove, reject) => {
resolve(2);
});
console.log(result);
}
console.log(3);
foo();
console.log(4);
代码执行结果
- 程序在一个线程上执行,一个线程可以创建多个协程。
- 父协程打印3。
- 执行foo函数。由于foo函数被async标记过,所以当进入该函数的时候,JavaScript 引擎会创建一个协程。线程切换到foo函数子协程。
- 执行子协程打印2。
- 将Promise的异步任务放入任务队列中执行。通过await关键词利用生成器原理暂停子协程的运行。将await后面的Promise对象,返回给父协程。
- 父协程答应4。
- 父协程等待await后面的Promise对象的执行结果,当Promise对象执行状态变为完成时,调用Promise对象的then方法。then方法,将运行生成器原理的next将协程由父协程切换到子协程继续运行,打印Promise的返回值2。
js程序的执行顺序
- 执行当前线程程序。遇到特殊函数会创建线程中的协程。将其他函数放到任务队列中。
- 线程程序执行完。
- 执行任务队列中的程序。
例子
async function main() {
let value1 = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve("执行成功1");
//reject("执行失败1");
}, 3000);
});
console.log(1);
let value2 = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve("执行成功2");
//reject("执行失败1");
}, 3000);
});
console.log(2);
console.log(value1 + value2);
}
main();