前端面试题积累(1)

148 阅读2分钟

线程任务、微任务、宏任务 相关

题目

阅读下面代码,我们只考虑浏览器环境下的输出结果,写出它们结果打印的先后顺序,并分析出原因。

console.log("AAAA");
setTimeout(() => console.log("BBBB"), 1000);
const start = new Date();
while (new Date() - start < 3000) {}
console.log("CCCC");
setTimeout(() => console.log("DDDD"), 0);
new Promise((resolve, reject) => {
	console.log("EEEE");
    foo.bar(100);
}).then(() => console.log("FFFF"))
.then(() => console.log("GGGG"))
.catch(() => console.log("HHHH"))
console.log("IIII")

答案

AAAA
CCCC
EEEE
IIII
HHHH
BBBB
DDDD

解析

题目考查重点是 js异步执行 宏任务 微任务。

一开始代码执行,输出AAAA

第二行代码开启一个定时器,我们称之为t1,这是一个异步任务且是宏任务,需要等到1秒后提交。

第四行是个while语句,需要等待3秒才能执行下面的代码,这里有个问题,就是3秒后上一个定时器t1的提交时间已经过了,但是线上的任务还没有执行结束,所以暂时不能打印结果,所以它排在宏任务的最前面了。

第五行又输出CCCC

第六行又开启一个定时器,我们称之为t2,它的提交时间是0秒,但是之前的t1任务还没有执行,还在等待,所以t2就排在t1的后面。都还需要等待,因为线程上的任务还没有执行完毕。

第七行new Promise将执行promise函数,它参数是一个回调函数,这个回调函数内的代码是同步的,它的异步核心在与resolve和reject,同时这个异步任务在任务队列中属于微任务,是优先与宏任务执行的。所以先打印输出同步代码EEEE

第九行中的代码是个不存在的对象,这个错误回抛给reject这个状态,也就是catch去处理,但是它是异步且是微任务,只有等到线程上的任务执行完毕,立马执行它,不管宏任务(定时器)等待多久了。

第十四行,这是线程上的最后一个任务,打印输出IIII

我们先找出线程上的同步代码,将结果依次排列出来 AAAA CCCC EEEE IIII

然后我们再找出所有异步任务中的微任务,把结果打印出来HHHH

最后我们再找出异步任务重的所有宏任务,这里t1排在前面,t2排在后面,输出结果是BBBB DDDD

所以综上, 结果是AAAA CCCC EEEE IIII HHHH BBBB DDDD