总结
前端资料汇总
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
-
框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。
-
算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 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)
})
分析执行顺序:
-
首先将整体代码作为一个宏任务执行,输出『start』
-
接着遇到
setTimeout
,0ms后将其回调函数放入宏任务队列 -
接下来遇到
Promise
, 由于Promise本身是立即执行函数, 所以先输出『children4』
3-1. 在Promise
中遇到setTimeout
, 将其回调放入宏任务队列中;整体代码执行完毕
-
然后检查并执行所有微任务, 因为没有微任务, 所以第一次事件循环结束,开始第二轮
-
执行
第2步
放入的宏任务,输出『children2』 5-1. 遇到Promise
,并直接调用了resolve
,将.then回调加入都微任务队列中 -
检查并执行所有微任务, 输出『children3』, 没有多余的微任务, 所以第二轮事件循环结束,开始第三轮事件循环
-
执行
3-1
中放入的宏任务, 输出『children5』, 并且调用了resolve
, 所以将对应的.then回调放入到微任务队列中 -
检查并执行所以微任务, 输出『children7』,遇到
setTimeout
,将其加入到宏任务队列中,开始第四轮事件循环 -
执行
第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的执行顺序:
-
执行完一个阶段的所有任务
-
执行完
nextTick
队列里面的内容 -
然后执行完微任务队列的内容
在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。setImmediate
和setTimeout
是相似的,但根据它们被调用的时间以不同的方式表现。
-
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
执行流程梳理:
-
代码都在
readFile
回调中,回调执行时处于poll
阶段 -
遇到
setTimeout
,虽然延时设置的是0, 但是相当于setTimeout(fn,1)
,将其回调函数放入后面的timers阶段 -
接下来遇到
setImmediate
,将其回调函数放入到后面的check阶段 -
遇到
process.nextTick
, 立即执行, 输出 『nextTick 1』 -
执行到下一个阶段check,输出『setImmediate』, 又遇到
nextTick
,执行输出『nextTick 2』 -
执行到下一个timers阶段, 输出『setTimeout』
这种机制其实类似于我们前面讲的微任务,但是并不完全一样,比如同时有nextTick
和Promise
的时候,肯定是nextTick
先执行,原因是nextTick
的队列比Promise
队列优先级更高。来看个例子:
setImmediate(() => {
console.log(‘setImmediate’);
});
Promise.resolve().then(()=>{
console.log(‘promise’)
})
process.nextTick(()=>{
console.log(‘nextTick’)
})
最后
其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)
《前端开发四大模块核心知识笔记》
最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。