Web前端最全如何跟面试官解释事件循环(1),web前端面试常用算法是什么

总结

前端资料汇总

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。

  • 算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯

  • 在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。

  • 要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
    喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!

最后执行结果如下:

script start

async1 start

async2

promise1

script end

async1 end

promise2

setTimeout

关于第3步代码执行分析:

async function async1() {

console.log(“async1 start”)

await async2()

console.log(“async1 end”)

}

改为Promise写法就是:

async function async1() {

new Promise((resolve, reject) =>{

console.log(“async1 start”)

resolve(async2())

}).then(()=>{

// 执行 async1 函数await之后的语句

console.log(“async1 end”)

})

}

再看下面一道题

案例2:代码执行结果是什么

console.log(“start”);

setTimeout(() => {

console.log(“children2”)

Promise.resolve().then(() =>{

console.log(“children3”)

})

}, 0)

new Promise(function(resolve, reject){

console.log(“children4”)

setTimeout(function(){

console.log(“children5”)

resolve(“children6”)

}, 0)

}).then(res =>{

console.log(“children7”)

setTimeout(() =>{

console.log(res)

}, 0)

})

分析执行顺序:

  1. 首先将整体代码作为一个宏任务执行,输出『start』

  2. 接着遇到setTimeout,0ms后将其回调函数放入宏任务队列

  3. 接下来遇到Promise, 由于Promise本身是立即执行函数, 所以先输出『children4』

3-1. 在Promise中遇到setTimeout, 将其回调放入宏任务队列中;整体代码执行完毕

  1. 然后检查并执行所有微任务, 因为没有微任务, 所以第一次事件循环结束,开始第二轮

  2. 执行第2步放入的宏任务,输出『children2』 5-1. 遇到Promise,并直接调用了resolve,将.then回调加入都微任务队列中

  3. 检查并执行所有微任务, 输出『children3』, 没有多余的微任务, 所以第二轮事件循环结束,开始第三轮事件循环

  4. 执行3-1中放入的宏任务, 输出『children5』, 并且调用了resolve, 所以将对应的.then回调放入到微任务队列中

  5. 检查并执行所以微任务, 输出『children7』,遇到setTimeout,将其加入到宏任务队列中,开始第四轮事件循环

  6. 执行第8步加入的宏任务, 输出『children6』, 没有任何微任务, 第四轮事件循环结束。

最后执行结果:

start

children4

children2

children3

children5

children7

children6

注意:有的小伙伴在第3步中容易错误的将.then的回调放入微任务队列;因为没有调用resolve或者reject之前是不算异步任务完成的, 所以不能将回调放入事件队列

Node和浏览器的事件循环的区别?


Node的事件循环是libuv实现的,引用一张官网的图:

Node的事件循环

图中表示的是事件循环包含的6个阶段,大体的task(宏任务)执行顺序是这样的:

  • timers定时器:本阶段执行已经安排的 setTimeout() 和 setInterval() 的回调函数。

  • pending callbacks待定回调:执行延迟到下一个循环迭代的 I/O 回调。

  • idle, prepare:仅系统内部使用,可以不必理会。

  • poll 轮询:检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,它们由计时器和 setImmediate() 排定的之外),其余情况 node 将在此处阻塞。

  • check 检测:setImmediate() 回调函数在这里执行。

  • close callbacks 关闭的回调函数:一些准备关闭的回调函数,如:socket.on('close', ...)

首先需要知道的是Node版本不同,执行顺序有所差异。因为Node v11之后, 事件循环的原理发生了变化,和浏览器执行顺序趋于一致,都是每执行一个宏任务就执行完微任务队列。

Node v10及以前,微任务和宏任务在Node的执行顺序:

  1. 执行完一个阶段的所有任务

  2. 执行完nextTick队列里面的内容

  3. 然后执行完微任务队列的内容

Node v10及以前的版本,微任务会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行微任务队列的任务:

图片.png

浏览器与Node执行顺序分别是什么


setTimeout(()=>{

console.log(‘timer1’)

Promise.resolve().then(function() {

console.log(‘promise1’)

})

}, 0)

setTimeout(()=>{

console.log(‘timer2’)

Promise.resolve().then(function() {

console.log(‘promise2’)

})

}, 0)

// 浏览器中:

timer1

promise1

timer2

promise2

// 在Node中:

timer1

timer2

promise1

promise2

在这个例子中,Node的逻辑如下(再强调一下Node v10及以下):

最初timer1和timer2就在timers阶段中。开始时首先进入timers阶段,执行timer1的回调函数,打印timer1,并将promise1.then回调放入微任务队列,同样的步骤执行timer2,打印timer2;至此,timer阶段执行结束,event loop进入下一个阶段之前,执行微任务队列的所有任务,依次打印promise1、promise2。

setImmediate 的setTimeout的区别

setImmediate大部分浏览器暂时不支持,只有IE10、11支持,具体可见MDN。setImmediatesetTimeout是相似的,但根据它们被调用的时间以不同的方式表现。

  • setImmediate设计用于在当前poll阶段完成后check阶段执行脚本 。

  • setTimeout 安排在经过最小(ms)后运行的脚本,在timers阶段执行。

举个例子:

setTimeout(() => {

console.log(‘setTimeout’);

}, 0);

setImmediate(() => {

console.log(‘setImmediate’);

});

其执行顺序为:

遇到setTimeout,虽然设置的是0毫秒触发,但是被node.js强制改为1毫秒,塞入times阶段 遇到setImmediate塞入check阶段 同步代码执行完毕,进入Event Loop 先进入times阶段,检查当前时间过去了1毫秒没有,如果过了1毫秒,满足setTimeout条件,执行回调,如果没过1毫秒,跳过 跳过空的阶段,进入check阶段,执行setImmediate回调 可见,1毫秒是个关键点,所以在上面的例子中,setImmediate不一定在setTimeout之前执行了。

process.nextTick()与 Promise回调谁先执行?

process.nextTick()是Node环境下的方法, 所以我们基于Node谈论。

process.nextTick()是一个特殊的异步API,其不属于任何的Event Loop阶段。事实上Node在遇到这个API时,Event Loop根本就不会继续进行,会马上停下来执行process.nextTick(),这个执行完后才会继续Event Loop。可以看一下个例子:

var fs = require(‘fs’)

fs.readFile(__filename, () => {

setTimeout(() => {

console.log(‘setTimeout’);

}, 0);

setImmediate(() => {

console.log(‘setImmediate’);

process.nextTick(() => {

console.log(‘nextTick 2’);

});

});

process.nextTick(() => {

console.log(‘nextTick 1’);

});

});

// 执行结果

nextTick 1

setImmediate

nextTick 2

setTimeout

执行流程梳理:

  1. 代码都在readFile回调中,回调执行时处于poll阶段

  2. 遇到setTimeout,虽然延时设置的是0, 但是相当于setTimeout(fn,1),将其回调函数放入后面的timers阶段

  3. 接下来遇到setImmediate,将其回调函数放入到后面的check阶段

  4. 遇到process.nextTick, 立即执行, 输出 『nextTick 1』

  5. 执行到下一个阶段check,输出『setImmediate』, 又遇到nextTick,执行输出『nextTick 2』

  6. 执行到下一个timers阶段, 输出『setTimeout』

这种机制其实类似于我们前面讲的微任务,但是并不完全一样,比如同时有nextTickPromise的时候,肯定是nextTick先执行,原因是nextTick的队列比Promise队列优先级更高。来看个例子:

setImmediate(() => {

console.log(‘setImmediate’);

});

Promise.resolve().then(()=>{

console.log(‘promise’)

})

process.nextTick(()=>{

console.log(‘nextTick’)

})

最后

其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《前端开发四大模块核心知识笔记》

最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值