首先我们看一个传统的程序的执行顺序
function one() {
return "i am one";
}
function two() {
return "i am two";
}
function three() {
return "i am three";
}
function run() {
console.log(one());
console.log(two());
console.log(three());
}
run();
// i am one
// i am two
// i am three
因为程序较为简单,看不出异步的请求过程,现在我们把程序做出修改,模拟一下异步过程
function one() {
return "i am one";
}
function two() {
setTimeout(() => {
return "i am two";
}, 3000);
}
function three() {
return "i am three";
}
function run() {
console.log(one());
console.log(two());
console.log(three());
}
run();
// i am one
// undefined
// i am three
由上看出two()返回的是undefined,这是因为two()里面写了一个setTimeout()方法,给two()加了一个3秒后执行的条件,但我们的程序是异步的,three()并不会等到two()执行之后再执行,所以就会出现undefined
在我们的实际开发中会遇到后面的程序需要等前面的程序执行完再执行的情况,那么什么方法可以让three()等two()执行完了后再执行呢?
把我们的程序由异步变成同步的就可以了,下面就需要用我们的Promise对象了
function one() {
return "i am one";
}
function two() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("i am two");
}, 3000);
});
}
function three() {
return "i am three";
}
function run() {
console.log(one());
console.log(two());
console.log(three());
}
run();
// i am one
// Promise {<pending>}
// i am three
上面的resolve是请求成功的状态,reject是请求失败的状态
可以得到程序的结果two()返回了一个Promis对象,是一个pending状态,也就是挂起(等待) 处于未决阶段,表示事情还是在挂起,最后的结果没有出来
因为再调用我们的two()的时候并没有声明需要等待two()执行完毕后再执行后面的程序,所以是一个padding状态
function one() {
return "i am one";
}
function two() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("i am two");
}, 3000);
});
}
function three() {
return "i am three";
}
async function run() {
console.log(one());
console.log(await two());
console.log(three());
}
run();
// i am one
// ....等待三秒之后(未打印,只是帮助理解)
// i am two
// i am three
async 是“异步”的简写,async是声明一个function是异步的
await的含义为等待,也就是 async 函数需要等待await后的函数执行完成并且有了返回结果(Promise对象)之后,才能继续执行下面的代码。await通过返回一个Promise对象来实现同步的效果
总结:async函数表示函数里面可能会有异步方法,await后面跟一个表达式,async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行。
下面再来一个简单的例子方便理解async和await
async function async1(){
console.log('async1 start'); //2
await async2();
console.log('async1 end') //5
}
async function async2(){
console.log('async2') //3
}
console.log('script start'); //1
async1();
console.log('script end') //4
// 输出顺序:
->script start
->async1 start
->async2
->script end
->async1 end
简单点说,await执行完表达式,会把它表达式后面的代码放到最后执行
可以看下面还有一个例子
async function async1() {
console.log("async1 start"); //2
await async2();
console.log("async1 end"); //9
}
async function async2() {
console.log("async2 start"); //3
await async3();
console.log("async2 end"); //8
}
async function async3() {
console.log("async3 start"); //4
await async4();
console.log("async3 end"); //7
}
async function async4() {
console.log("async4"); //5
}
console.log("script start"); //1
async1();
console.log("script end"); //6
// script start
// async1 start
// async2 start
// async3 start
// async4
// script end
// async3 end
// async2 end
// async1 end
如果不能理解,可以看下面的图,await表达式后面的代码放到一个队列中,先进的后出,所以前面的后执行