js中async和await执行顺序详解

268 阅读2分钟

前言

async和await是ES6提出来的处理异步函数的。但是它们是如何执行的,执行顺序又是怎样的?这篇文章将会为你揭晓。

async/await

  • async/await是一种编写异步代码的新方法。之前异步代码的方案是回调和promise。
  • async/await是建立在promise的基础上。
  • async/await像promise一样,也是非阻塞的。
  • async/await让异步代码看起来、表现起来更像同步代码。

async怎么处理返回值

async function testAsync() {
    return 'hello async';
}
let result = testAsync();
console.log(result);  // Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello async"}

小结:从结果中可以看出async函数返回的是一个promise对象,如果在函数中return一个直接量,async会把这个量通过Promise.resolve()封装成Promise对象。

如果async函数没有返回值

async function testAsync1() {
    console.log('hello, async!');
}
let result = testAsync1();
console.log(result);    // Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "undefined"}

小结:结果返回了Promise.resolve(undefined);

await等待的是一个表达式,这个表达式的返回值可以是一个Promise对象也可以是别的值。很多人以为await会一直等待之后的表达式执行完成后才会继续执行后面的代码,实际上await是一个让出线程的标志。await后面的函数会先执行一遍,然后就会跳出整个async函数来执行后面js栈(后面会详述)的代码,等本轮事件循环执行完了之后又会跳回到async函数中等待await后面表达式的返回值,如果返回值为非promise则继续执行async函数后面的代码,否则将返回的promise队列。

async/await 执行顺序

代码示例:

function testSometing() {
 console.log("执行testSometing");
 return "testSometing";
}

async function testAsync() {
 console.log("执行testAsync");
 return Promise.resolve("hello async");
}

async function test() {
 console.log("test start...");
 const v1 = await testSometing();//关键点1
 console.log(v1);
 const v2 = await testAsync();
 console.log(v2);
 console.log(v1, v2);
}

test();

var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//关键点2

promise.then((val)=> console.log(val));
console.log("test end...")

// 执行结果
//test start...
//执行testSometing
//promise start..
//test end...
//testSometing
//执行testAsync
//promise
//hello async
//testSometing hello async

执行顺序分析:

// 执行栈
console.log("test start...");

//执行到const v1 = await testSometing()时,因为await会让出线程,就会去执行后面的代码
var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//关键点2
// 执行栈
console.log("test start...");
console.log("执行testSometing");
////////
console.log("promise start..");
console.log("test end...");

// Promise队列:
promise.then((promise)=> console.log(promise));

继续执行await后面的代码

// 执行栈
console.log("test start...");
console.log("执行testSometing");
////////
console.log("promise start..");
console.log("test end...");
///////
console.log(v1);// v1 = testSometing

// Promise队列:
promise.then((promise)=> console.log(promise));

执行到const v2 = await testAsync();

// 执行栈
console.log("test start...");
console.log("执行testSometing");
////////
console.log("promise start..");
console.log("test end...");
///////
console.log(v1);// v1 = testSometing
//////
console.log("执行testAsync");

// Promise队列:
promise.then((promise)=> console.log(promise));

跳出test,继续执行后面的代码

// 执行栈
console.log("test start...");
console.log("执行testSometing");
////////
console.log("promise start..");
console.log("test end...");
////////
console.log(v1);// v1 = testSometing
////////
console.log("执行testAsync");
////////
console.log(promise);

继续执行await后面的代码

// 执行栈
console.log("test start...");
console.log("执行testSometing");
////////
console.log("promise start..");
console.log("test end...");
////////
console.log(v1);// v1 = testSometing
////////
console.log("执行testAsync");
////////
console.log(promise);
////////
console.log("hello async");
console.log("testSometing hello async");