Skip to main content

Fastify

koa

  • Application: 基本服务器框架
  • Context: 服务器框架基本数据结构的封装,用以 http 请求解析及响应
  • Middleware: 中间件,也是洋葱模型的核心机制

无论Vue,还是react,还是Koa,都是建立一个数组,这个数组就是执行函数的队列,Koa把每个中间件和路由都做成一个task,放到队列里面, koa则使用了递归的形式,写了个 compose 方法,compose方法里面返回一个dispatch函数, 初始化传入下标为 0,也就是 第一个task,这个方法传入 i为参数,代表执行第 i 个中间件,而 next() 函数将会执行下一个中间件 dispatch(i+1) 当最后一个中间件函数执行 next() 时,直接return 我们的 dispatch 函数。

function compose(middlewares) {
return (ctx) => {
const dispatch = (i) => {
const middleware = middlewares[i];
if (i === middlewares.length) {
return;
}
return middleware(ctx, () => dispatch(i + 1));
};
return dispatch(0);
};
}

如何监控文件的变动

  • 在 node 中调用 API fs.watch
  • 在 linux 中原理是 inotify,macos 中原理是 FSEvents,windows 中原理是 ReadDirectoryChangesW
  • 由于内核对文件监控更加细粒度,更加敏感,当每次修改文件时可能触发内核多次调用,需要防抖
  • 注意软链接,读写权限等文件系统属性

在 Node 应用中如何利用多核心CPU的优势

  • 使用 cluster 模块

nodejs 负载均衡

  • Node.js 集群:适用于单台机器上的负载均衡。优点是易于实现,但它不能在多台机器之间分配负载。

外部负载均衡器 nginx

http {
upstream myapp {
server localhost:8000;
server localhost:8001;
server localhost:8002;
}

server {
listen 80;

location / {
proxy_pass http://myapp;
}
}
}
  • 第 4 层负载均衡通常更快并且适用于较低级别的 TCP/UDP 流量,而第 7 层负载均衡提供了更高级的流量管理功能,特别适用于复杂的 HTTP/HTTPS 应用。

Node 中如何判断一个路径是文件还是文件夹

const statInfo = fs.lstatSync("./xx").statInfo.isDirectory()

  • isFile():检测是否为常规文件
  • isDirectory():检测是否为文件夹

Node 如何进行进程间通信

对于 spawn/fork 出来的父子进程来说,可以通过 pipe 的方式

  • process.on('message')/process.send
  • stdin.on/stdout.write

对于并无相关的进程

  • socket
  • message queue

Promise 在异步资源的生命周期 (async_hooks) 中是如何被销毁的

  • Promise 在 Node.js 的异步资源生命周期中并没有一个显式的“销毁”阶段。它们被解决或拒绝后仍然存在于内存中,但它并不直接控制对象何时被垃圾回收。垃圾回收的时机取决于 V8 引擎的垃圾回收策略和对象是否还有活跃的引用。

在 node 中如何监听异步资源的生命周期

  • async_hooks 创建钩子的函数接受一个包含不同生命周期事件回调的对象。这些事件包括:

  • init: 当一个异步资源被创建时触发。

  • before: 在异步资源的回调被调用之前触发。

  • after: 在异步资源的回调被调用之后触发。

  • destroy: 当一个异步资源被销毁时触发。

express 错误处理中间件

中间件有4个参数 第一个就是err

在 Node 中如何读取可读流的内容

let data = "";
stream.on("data", (chunk) => (data += chunk));
stream.on("end", () => console.log(data));

请简述下 Node 与浏览器环境中的事件循环

众所周知,js 是单线程的语言,同一时间只做一件事,单线程也就导致一个任务执行完才能执行下一个任务,一旦某个任务执行时间太长就容易造成阻塞,为了解决这一问题,js 引入了事件循环机制

  • js 单线程任务分为同步任务和异步任务

  • 同步任务:立即执行的任务,直接在主线程上排队执行 异步任务:不进入主线程,而是在异步任务有了结果之后将回调函数放入到任务队列中等待主线程空闲时调用执行

  • 主线程任务执行完毕后从任务队列中不断读取任务,放入到主线程去执行,这个过程是循环不停的

  • 而异步任务又可以分为宏任务和微任务

  • 微任务和宏任务 常见微任务:Promise.then,Object.observe,MutationObserver,process.nextTick(Node 环境) 常见宏任务:setTimeout,ajax,dom 事件,setImmediate(Node 环境),requestAnimationFrame

  • 同步任务执行完毕后会开始从调用栈中去执行异步任务,优先执行的是微任务,当微任务队列清空后才会去执行宏任务,每次单个宏任务执行完毕后会去检查微任务队列是否为空,如果不为空会按照先入先出的原则执行微任务,待微任务队列清空后再执行下一个宏任务,如此循环往复,这种运行机制就叫做事件循环

在 Node 中流 (stream) 分为几类,有哪些应用场景

  • Writable: 可以写入数据的流(例如,fs.createWriteStream())。
  • Readable: 可以从中读取数据的流(例如,fs.createReadStream())。
  • Duplex: Readable 和 Writable 的流(例如,net.Socket)。
  • Transform: 可以在写入和读取数据时修改或转换数据的 Duplex 流(例如,zlib.createDeflate())

在 Node 中如何读写文件

  1. open
  2. read
  3. close

如何正确得知某张图片的 MIME 格式

  • 浏览器:file.type

  • Node.js:

  • mime-types mime.lookup(pathToFile);

  • 使用文件扩展名

  • 读取文件的二进制签名

express 中间件

  • 应用级中间件:绑定到 app 对象的中间件,对所有请求生效。
  • 路由级中间件:绑定到 express.Router() 实例的中间件,只对特定路由生效。
  • 错误处理中间件:专门用于处理错误的中间件。
  • 内置中间件:Express 内置的中间件,如 express.static、express.json 等。
  • 第三方中间件:由社区提供的中间件,需单独安装。

检查流的类型

  • Readable Writable 为 true

  • read pipe === function write end === function

  • instanceof

v8 中的垃圾回收机制分为三种