Js中async/await的执行顺序详解
前言
虽然大家知道async/await,但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解JavaScript的async/await(如果对async/await不熟悉可以先看下这篇文章)后拓展了一下,我理了一下await之后js的执行顺序,希望可以给别人解疑答惑,先简单介绍一下async/await。
- async/await是一种编写异步代码的新方法。之前异步代码的方案是回调和promise。
- async/await是建立在promise的基础上。
- async/await像promise一样,也是非阻塞的。
- async/await让异步代码看起来、表现起来更像同步代码。这正是其威力所在。
async怎么处理返回值
asyncfunctiontestAsync(){ return"helloasync"; } letresult=testAsync(); console.log(result)
输出结果:
Promise{[[PromiseStatus]]:"resolved",[[PromiseValue]]:"helloasync"}
从结果中可以看到async函数返回的是一个promise对象,如果在函数中return一个直接量,async会把这个直接量通过Promise.resolve()封装成Promise对象。
如果asyn函数没有返回值
asyncfunctiontestAsync1(){ console.log("helloasync"); } letresult1=testAsync1(); console.log(result1);
结果
helloasync Promise{[[PromiseStatus]]:"resolved",[[PromiseValue]]:undefined}
结果返回Promise.resolve(undefined)。
await做了什么处理
从字面意思上看await就是等待,await等待的是一个表达式,这个表达式的返回值可以是一个promise对象也可以是其他值。
很多人以为await会一直等待之后的表达式执行完之后才会继续执行后面的代码,实际上await是一个让出线程的标志。await后面的函数会先执行一遍,然后就会跳出整个async函数来执行后面js栈(后面会详述)的代码。等本轮事件循环执行完了之后又会跳回到async函数中等待await
后面表达式的返回值,如果返回值为非promise则继续执行async函数后面的代码,否则将返回的promise放入promise队列(Promise的JobQueue)
async/await执行顺序
先看一个例子
functiontestSometing(){ console.log("执行testSometing"); return"testSometing"; } asyncfunctiontestAsync(){ console.log("执行testAsync"); returnPromise.resolve("helloasync"); } asyncfunctiontest(){ console.log("teststart..."); constv1=awaittestSometing();//关键点1 console.log(v1); constv2=awaittestAsync(); console.log(v2); console.log(v1,v2); } test(); varpromise=newPromise((resolve)=>{console.log("promisestart..");resolve("promise");});//关键点2 promise.then((val)=>console.log(val)); console.log("testend...")
输出结果:
teststart... 执行testSometing promisestart.. testend... testSometing 执行testAsync promise helloasync testSometinghelloasync
当test函数执行到
constv1=awaittestSometing();
的时候,会先执行testSometing这个函数打印出“执行testSometing”的字符串,然后因为await会让出线程就会区执行后面的
varpromise=newPromise((resolve)=>{console.log("promise start..");resolve("promise");});//关键点2
然后打印出“promisestart..”接下来会把返回的这promise放入promise队列(Promise的JobQueue),继续执行打印“testend...”,等本轮事件循环执行结束后,又会跳回到async函数中(test函数),等待之前await后面表达式的返回值,因为testSometing不是async函数,所以返回的是一个字符串“testSometing”,test函数继续执行,执行到
constv2=awaittestAsync();
和之前一样又会跳出test函数,执行后续代码,此时事件循环就到了promise的队列,执行promise.then((val)=>console.log(val));then后面的语句,之后和前面一样又跳回到test函数继续执行。
这个就是在async/await函数之后js的执行顺序,我们再看一个列子把testSometing函数前面加上async
asyncfunctiontestSometing(){ console.log("执行testSometing"); return"testSometing"; } asyncfunctiontestAsync(){ console.log("执行testAsync"); returnPromise.resolve("helloasync"); } asyncfunctiontest(){ console.log("teststart..."); constv1=awaittestSometing(); console.log(v1); constv2=awaittestAsync(); console.log(v2); console.log(v1,v2); } test(); varpromise=newPromise((resolve)=>{console.log("promisestart..");resolve("promise");});//3 promise.then((val)=>console.log(val)); console.log("testend...")
输出结果:
teststart... 执行testSometing promisestart.. testend... promise testSometing 执行testAsync helloasync testSometinghelloasync
和上一个例子比较发现promise.then((val)=>console.log(val));先与console.log(v1);执行了,原因是因为现在testSometing函数加了async,返回的是一个Promise对象要要等它resolve,所以将当前Promise推入队列,所以会继续跳出test函数执行后续代码。之后就开始执行promise的任务队列了,所以先执行了promise.then((val)=>console.log(val));因为这个Promise对象先推入队列;
总结
写到这里大家应该已经清楚了使用async/await进行异步操作时js的执行顺序,在研究过程中还发现了js的任务队列执行顺序的问题,就下次再述。如果大家对有什么意见或建议可以指出。本篇是我第一次发布文章,希望大家不吝赐教。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。