挑战一轮大厂后的面试总结 (含六个方向) - nodejs 篇

本文总结了作者在面试过程中遇到的Node.js相关问题,包括Node.js如何支持高并发、事件循环机制、创建进程线程、Koa2的洋葱模型、Stream以及npm安装过程等知识点。强调了基础的重要性,并给出了详细的技术解析和示例,适合面试复习和学习。
摘要由CSDN通过智能技术生成

在去年底开始换工作,直到现在算是告了一个段落,断断续续的也面试了不少公司,现在回想起来,那段时间经历了被面试官手撕,被笔试题狂怼,悲伤的时候差点留下没技术的泪水。

这篇文章我打算把我找工作遇到的各种面试题(每次面试完我都会总结)和我自己复习遇到比较有意思的题目,做一份汇总,年后是跳槽高峰期,也许能帮到一些小伙伴。

先说下这些题目难度,大部分都是基础题,因为这段经历给我的感觉就是,不管你面试的是高级还是初级,基础的知识一定会问到,甚至会有一定的深度,所以基础还是非常重要的。

我将根据类型分为几篇文章来写:

面试总结:javascript 面试点汇总(万字长文)(已完成) 强烈大家看看这篇,面试中 js 是大头

面试总结:nodejs 面试点汇总(已完成)

面试总结:浏览器相关 面试点汇总(已完成)

面试总结:css 面试点汇总(已完成)

面试总结:框架 vue 和工程相关的面试点汇总(已完成)

面试总结:面试技巧篇(已完成)

六篇文章都已经更新完啦~

这篇文章是对 nodejs 相关的题目做总结,欢迎朋友们先收藏在看。

先看看目录

目录

Q: 怎么看 nodejs 可支持高并发

这个问题涉及了好几个方面啊,聊的好,是个很好的加分项。可按照以下步骤给面试官解释

  1. nodejs 的单线程架构模型

nodejs 其实并不是真正的单线程架构,因为 nodejs 还有I/O线程存在(网络I/O、磁盘I/O),这些I/O线程是由更底层的 libuv 处理,这部分线程对于开发者来说是透明的。 JavaScript 代码永远运行在V8上,是单线程的。

所以从开发者的角度上来看 nodejs 是单线程的。

来张网图:

v8

注意看图的右边有个 Event Loop,接下来要讲的重点

单线程架构的优势和劣势:

优势:

  • 单线程就一个线程在玩,省去了线程间切换的开销
  • 还有线程同步的问题,线程冲突的问题的也不需要担心

劣势:

  • 劣势也很明显,现在起步都是 4 核,单线程没法充分利用 cpu 的资源
  • 单线程,一旦崩溃,应用就挂掉了,大家调试脚本也知道一旦执行过程报错了,本次调试就直接结束了
  • 因为只能利用一个 cpu ,一旦 cpu 被某个计算一直占用, cpu 得不到释放,后续的请求就会一直被挂起,直接无响应了

当然这些劣势都已经有成熟的解决方案了,使用 PM2 管理进程,或者上 K8S 也可以

  1. 核心:事件循环机制

那你个单线程怎么支持高并发呢?

核心就要在于 js 引擎的事件循环机制(我觉得这个开场还挺不错)

浏览器和 nodejs 的事件循环是稍有区别的,先给面试官简单说下事件循环的核心,执行栈、宏队列和微队列,具体的介绍可以看我以前写的一篇总结 js 事件循环

然后重点说 nodejs 事件循环的差异点,因不想把两个问题混在一起,所以独立成一个问题,具体讲解大家稍微往下翻看下一个问题的解答。

  1. 给出个结论 nodejs 是异步非阻塞的,所以能扛住高并发

来个个栗子:

比如有个客户端请求A进来,需要读取文件,读取文件后将内容整合,最后数据返回给客户端。但在读取文件的时候另一个请求进来了,那处理的流程是怎么样的?

灵魂画手,我整了张图,大家理解就好

loop

  • 请求A进入服务器,线程开始处理该请求
  • A 请求需要读取文件,ok,交给文件 IO 处理,但是处理得比较慢,需要花 3 秒,这时候 A 请求就挂起(这个词可能不太恰当),等待通知,而等待的实现就是由事件循环机制实现的,
  • 在A请求等待的时候,cpu 是已经被释放的,这时候B请求进来了, cpu 就去处理B请求
  • 两个请求间,并不存在互相竞争的状态。那什么时候会出现请求阻塞呢?涉及到大量计算的时候,因为计算是在 js 引擎上执行的,执行栈一直卡着,别的函数就没法执行,举个栗子,构建一个层级非常深的大对象,反复对这个这个对象 JSON.parse(JSON.stringify(bigObj))
  1. 有机会的话可以给面试官扩展 同步、异步、阻塞、非阻塞 这个几个概念

同步和异步关注的是消息通信机制。

  • 同步:在发起一个调用后,在没有得到结果前,该调用不返回,知道调用返回,才往下执行,也就是说调用者等待被调用方返回结果。

  • 异步:在发起一个调用后,调用就直接返回,不等待结果,继续往下执行,而执行的结果是由被调用方通过状态、通知等方式告知调用方,典型的异步编程模型比如 Node.js

阻塞和非阻塞,关注的是在等待结果时,线程的状态。

  • 阻塞:在等待调用结果时,线程挂起了,不往下执行
  • 非阻塞:与上面相反,当前线程继续往下执行

参考资料:
https://www.zhihu.com/question/19732473
https://zhuanlan.zhihu.com/p/41118827

Q: 介绍下 nodejs 的事件循环

这里假设大家已经对浏览器的事件循环有了解,看下图:

node-loop

如上图,事件循环中细分为这六个阶段,依次如下:

  1. Timers: 定时器 Interval Timoout 回调事件,将依次执行定时器回调函数
  2. Pending: 一些系统级回调将会在此阶段执行
  3. Idle,prepare: 此阶段"仅供内部使用"
  4. Poll: IO回调函数,这个阶段较为重要也复杂些,
  5. Check: 执行 setImmediate() 的回调
  6. Close: 执行 socket 的 close 事件回调
开发需要关系的阶段

与我们开发相关的三个阶段分别是 Timers Poll Check

Timers :执行定时器的回调,但注意,在 node 11 前,连续的几个定时器回调会连续的执行,而不是像浏览器那样,执行完一个宏任务立即执行微任务。

Check :这个阶段执行 setImmediate() 的回调,这个事件只在 nodejs 中存在。

Poll :上面两个阶段的触发,其实是在 poll 阶段触发的,poll 阶段的执行顺序是这样的。

  1. 先查看 check 阶段是否有事件,有的话执行
  2. 执行完 check 阶段后,检查 poll 阶段的队列是否有事件,若有则执行
  3. poll 的队列执行完成后,执行 check 阶段的事件

在 nodejs 中也是有宏任务和微任务的, nodejs 中除了多了 process.nextTick ,宏任务、微任务的分类都是一致的。

那么微任务是在什么时候执行呢?

在上图,黄色的几个阶段的旁边挨着个小块 microtask,每个阶段执行后就立即执行微任务队列里的事件。

下面有个栗子说明。

微队列的栗子

如下代码:

const fs = require('fs');
const ITERATIONS_MAX = 3;
let iteration = 0;
const timeout = setInterval(() => {
   
    console.log('START: setInterval', 'TIMERS PHASE');
    if (iteration < ITERATIONS_MAX) {
   
        setTimeout(() => {
   
            console.log('setInterval.setTimeout', 'TIMERS PHASE');
        });
        fs.readdir('./image', (err, files) => {
   
            if (err) throw err;
            console.log('fs.readdir() callback: Directory contains: ' + files.length + ' files', 'POLL PHASE');
        });
        setImmediate((
  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值