浅谈JS执行顺序

浅谈JS执行顺序

async function f() {
    setTimeout(()=>{
        return 1
    },1000)
}
async function aaa(){
    const bbb = await f()
    console.log('bbb',bbb);
}
aaa()

​ 今天在学async、await的时候写了上面那个代码,输出结果竟然是undefined,搜了好多资料发现是执行顺序的原因。下面谈谈今天我学到的东西

JS EventLoop 事件循环

因为JS有同步任务和异步任务,异步任务又分为**宏任务(macrotask)微任务( microtask )**两种

我将JS代码执行分为3块部分:执行队列、宏任务队列、微任务队列

JS代码执行时先将所有代码放到执行队列,在执行队列中碰到宏任务时,将之放到宏任务队列等候,遇到微任务时放到微任务队列等候,执行队列的代码执行完毕时检查微任务队列,有则放到执行队列,无则检查宏任务队列,有宏任务则放到执行队列

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');

//打印结果如下
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

这是一道经典题目了,这边先来分析一下

首先将所有代码放到执行队列,打印**‘script start’**

碰到setTimeout,将**‘setTimeout’**放到宏任务队列等待(压入宏任务栈中计时器会开启,不会等待执行队列结束后开启,但是其中代码不会执行)

然后调用async1()打印’async1 start’,在async1里碰到了await async2(),调用打印**‘async2’,然后将’async1 end’**放到微任务队列等待

await async2()
console.log('async1 end')

等价为

Promise.resolve(async2()).then(() => {
	console.log('async1 end')
})

继续执行new Promise,打印**‘promise1’,因为then’promise2’**放到微任务队列

然后打印**‘script end’**

此时执行队列中没有代码了,检查微任务队列,按照先后顺序打印**‘async1 end’’promise2’**

微任务队列执行完毕后检查宏任务队列,打印**‘setTimeout’**后全部执行

所以在我的代码中,bbb并不为1,而是f()没有返回值为undefinded,而setTimeout里的return是其自身的返回值

变化

async function async1() {
    console.log('async1 start');
    await async2();
    //更改如下:
    setTimeout(function() {
        console.log('setTimeout1')
    },0)
}
async function async2() {
    //更改如下:
    setTimeout(function() {
        console.log('setTimeout2')
    },0)
}
console.log('script start');

setTimeout(function() {
    console.log('setTimeout3');
}, 0)
async1();

new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');

//打印结果:
script start
async1 start
promise1
script end
promise2
setTimeout3
setTimeout2
setTimeout1

此处**await async2()之后的’setTimeout1’**被一起带到了宏任务队列中
一次修改 22/1/17
二次修改 22/1/25
参考: https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值