Files
zhuangang/topics/backend/nodejs/interview.md
T

4.0 KiB
Raw Blame History

id, title, type, domain, stack, tags, level, related, week
id title type domain stack tags level related week
backend.nodejs.interview Node.js 面试题 interview backend
nodejs
Node.js
事件循环
Express
NestJS
面试
basic
backend.nodejs.express-nest
14
16

Node.js 面试题

基础

【基础】Node 的事件循环是怎样的?

参考答案:单线程执行 JS,I/O 由 libuv 异步完成。主要阶段:timers → pending callbacks → poll → check → close callbacks;每个回调执行完后先清空 process.nextTick 队列,再清空 Promise 微任务队列。

追问:setTimeout(fn, 0) 和 setImmediate 谁先执行?→ 在主模块中顺序不确定(取决于进入事件循环时计时器是否到期);在 I/O 回调中 setImmediate 一定先执行。

【基础】Node 适合什么场景?

参考答案:I/O 密集、高并发连接:BFF、API 网关、实时推送(WebSocket / SSE)、工具链。不适合长时间的 CPU 计算,否则阻塞事件循环;需要时用 worker_threads 或拆到其他服务。

追问:怎么发现事件循环被阻塞?→ 监控事件循环延迟(perf_hooks.monitorEventLoopDelay),用 CPU profile 找热点。

【基础】Express 中间件的执行原理?

参考答案:按注册顺序组成链,每个中间件处理后调用 next() 进入下一个,不调用则请求在此结束;错误处理中间件有 4 个参数,next(err) 或 Express 5 中 async 函数抛错时跳转过去。

追问:和 Koa 的洋葱模型有什么区别?→ Koa 的 await next() 可以在后续中间件执行完后继续执行后半段逻辑,天然适合计时和统一响应处理;Express 需要监听 res 的 finish 事件实现类似效果。

进阶

【进阶】NestJS 的依赖注入有什么好处?

参考答案:类声明依赖,由容器创建和注入;便于替换实现(测试中注入假的服务)、统一生命周期管理、模块边界清晰;配合管道、守卫、拦截器形成统一规范。

追问:和 FastAPI 的 Depends 比较?→ 思想相同,FastAPI 基于函数参数声明,Nest 基于类构造函数和装饰器元数据。

【进阶】Node 服务如何处理未捕获的异常?

参考答案:请求级错误用统一错误处理中间件;进程级监听 uncaughtException / unhandledRejection 记录日志后退出,由进程管理器(容器编排 / systemd / PM2)重启;不要在未知状态下继续运行。

追问:为什么不能捕获后继续运行?→ 程序可能处于不一致的状态(连接、内存中的数据),继续运行可能产生更隐蔽的错误。

【进阶】Node 如何利用多核?

参考答案:多进程(cluster 或容器多副本 + 负载均衡)处理更多请求;worker_threads 处理 CPU 计算。服务要无状态,会话等放在 Redis。

追问:WebSocket 多实例怎么广播?→ 通过 Redis Pub/Sub 或消息队列在实例之间转发,负载均衡开启会话保持或使用支持多实例的方案。

场景题

【场景题】给 AI 应用做 BFF,你会做哪些事?

参考答案:统一鉴权、限流、request id;首屏并行聚合与降级;SSE 流式透传、断开时中止上游、超时控制、上游错误以事件形式通知;保持薄层。详见AI BFF 场景。

追问:怎么测试流式接口?→ 启动应用监听随机端口,用 fetch 读取响应,断言事件内容和顺序、错误事件和响应头,见示例测试。

【场景题】Node 服务内存持续上涨,怎么排查?

参考答案:观察堆内存趋势;在不同时间点生成堆快照对比,找增长的对象和引用链;常见原因:全局缓存无上限、事件监听未移除、闭包持有大对象、定时器未清理。修复后压测验证。

追问:线上怎么安全地拿堆快照?→ 在摘除流量的单个实例上进行,快照期间进程会暂停,注意快照可能包含敏感数据。