nodejs面试笔记

在 Node.js 中,“Node”这个词可以从多个角度理解。Node.js 是一个基于 JavaScript 的运行时环境,它使得开发者可以使用 JavaScript 来编写服务器端的应用程序,而不仅仅局限于在浏览器中使用 JavaScript。

1. Node.js 是什么?

Node.js 是一个基于 Chrome V8 JavaScript 引擎 构建的运行时环境,用于构建服务器端和网络应用。它由 Ryan Dahl 于 2009 年创建,并且极大地简化了使用 JavaScript 进行后端开发的过程。

Node.js 的核心特点是 非阻塞non-blocking)和 事件驱动event-driven),这使得它非常适合构建高性能、高并发的应用,如网络服务器、实时应用程序等。

2. Node.js 的工作原理

Node.js 是单线程的,但通过异步 I/O 操作可以处理大量的并发请求。它使用了 事件循环(event loop)和 回调函数(callback)的方式来处理异步任务。

  • 事件驱动:Node.js 内部基于事件循环模型,所有 I/O 操作(如网络请求、文件读写等)都是异步的,这意味着操作执行时不会阻塞主线程。
  • 非阻塞 I/O:通过非阻塞 I/O,Node.js 可以同时处理数千个请求,而不需要为每个请求创建一个新的线程。

工作流程示例:

  1. Node.js 接收到客户端请求。
  2. 如果请求涉及 I/O 操作(例如数据库查询),它会异步处理这些操作,允许主线程继续处理其他请求。
  3. 当 I/O 操作完成后,会将结果通过回调函数或 Promise 返回。
  4. 这种方式大大提高了效率,因为不必等待每个 I/O 操作完成后再处理下一个请求。

3. Node.js 的特点

3.1 单线程和事件驱动

Node.js 使用单线程处理事件,利用事件循环和异步 I/O 来实现高效的并发处理。它的事件驱动模型允许在主线程中处理大量的连接,而不会创建线程池或进行多线程并发。

  • 优点

    • 高效的资源利用,特别是在处理 I/O 密集型任务时。
    • 没有线程切换开销。
    • 简化了编程模型,不必考虑线程安全问题。
  • 缺点

    • 对 CPU 密集型任务不太友好,因为它可能会阻塞整个事件循环,导致其他请求不能及时得到处理。

3.2 异步编程模型

Node.js 的核心异步编程模型基于回调、Promiseasync/await。大部分的 I/O 操作(如文件读写、网络请求、数据库查询等)都是异步的,这意味着它们不会阻塞主线程。

1
2
3
4
5
6
7
8
9
10
11
12
// 简单的异步读取文件的例子
const fs = require('fs');

fs.readFile('example.txt', 'utf-8', (err, data) => {
if (err) {
console.error('Error reading file', err);
} else {
console.log('File contents:', data);
}
});

console.log('This will print before file is read.');

在这个例子中,文件读取是异步的,所以 readFile 函数会立即返回,继续执行 console.log()。当文件读取完成后,回调函数会被执行。

3.3 模块系统

Node.js 采用了基于 CommonJS 的模块系统。通过 require() 引入模块,使用 module.exports 导出模块。

1
2
3
4
5
6
7
8
// 导出模块
module.exports = function add(a, b) {
return a + b;
};

// 导入模块
const add = require('./add');
console.log(add(2, 3)); // 输出 5

4. Node.js 的常用场景

Node.js 由于其异步、事件驱动的特点,特别适合以下几种场景:

4.1 Web 服务器

Node.js 非常适合用于构建高并发、高性能的 Web 服务器。由于其单线程、非阻塞 I/O 模型,Node.js 可以同时处理大量请求,而不会因为某些请求的 I/O 操作阻塞服务器。

1
2
3
4
5
6
7
8
9
10
11
12
const http = require('http');

// 创建简单的 HTTP 服务器
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});

server.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});

4.2 实时应用程序

由于 Node.js 是事件驱动的,它非常适合构建需要实时响应的应用,如聊天应用、在线游戏、实时协作工具等。

一个常见的例子是 WebSocket 协议的实现,允许服务器和客户端之间进行双向的、实时的通信。

4.3 RESTful API

Node.js 非常适合用于构建 RESTful API,特别是在处理高并发的情况下。结合 Express.js 等框架,可以快速构建灵活的 API。

1
2
3
4
5
6
7
8
9
10
11
const express = require('express');
const app = express();

// 创建简单的 RESTful API
app.get('/', (req, res) => {
res.send('Hello World!');
});

app.listen(3000, () => {
console.log('API listening on http://localhost:3000');
});

4.4 微服务架构

Node.js 由于其轻量级和高效特性,常被用于微服务架构中。可以将复杂的应用拆分为多个小型服务,利用 Node.js 构建每个微服务,并通过 API 进行通信。

5. Node.js 的生态系统

Node.js 拥有庞大的包管理系统 npm,通过 npm 可以轻松安装和管理项目所需的第三方依赖。Node.js 生态中有大量的开源库和工具,涵盖了 Web 开发、数据库连接、测试框架、工具链等各个方面。

  • Express:轻量级的 Web 框架,用于快速构建 Web 应用和 API。
  • Koa:由 Express 原作者开发的更简洁的 Web 框架。
  • Socket.io:用于构建实时应用(如聊天应用)的 WebSocket 框架。
  • Mongoose:用于与 MongoDB 数据库交互的对象数据建模(ODM)工具。
  • MochaJest:流行的测试框架,方便开发者编写单元测试和集成测试。

6. 总结

Node.js 是一个强大、灵活且高效的 JavaScript 运行时,它的非阻塞 I/O 和事件驱动模型使得它非常适合构建高并发的应用程序。通过丰富的生态系统,Node.js 为开发者提供了大量工具和库,使得服务器端开发变得更加高效和简便。

Node.js 的设计理念和异步编程模型非常适合 I/O 密集型的任务,如 Web 服务器、API、实时应用等。在 CPU 密集型任务中,由于其单线程特性,Node.js 可能并不是最佳选择,但通过一些技术手段(如子进程或多线程库),也可以处理这类任务。