Skip to content

Node.js 完全指南

目录

Node.js 简介

什么是 Node.js

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境。它使得开发者可以使用 JavaScript 来编写服务器端程序。Node.js 采用事件驱动、非阻塞 I/O 模型,使其轻量且高效。

特点

  1. 单线程事件循环

    • 基于事件驱动
    • 非阻塞 I/O
    • 高并发处理能力
  2. 跨平台

    • 支持 Windows、macOS、Linux
    • 统一的 API
    • 良好的可移植性
  3. 强大的生态系统

    • npm 包管理器
    • 大量的第三方模块
    • 活跃的社区

核心概念

1. 事件循环

javascript
console.log("开始");

setTimeout(() => {
  console.log("定时器");
}, 0);

Promise.resolve().then(() => {
  console.log("Promise");
});

process.nextTick(() => {
  console.log("nextTick");
});

console.log("结束");

// 输出顺序:
// 开始
// 结束
// nextTick
// Promise
// 定时器

2. 回调函数

javascript
const fs = require("fs");

fs.readFile("example.txt", "utf8", (err, data) => {
  if (err) {
    console.error("读取文件失败:", err);
    return;
  }
  console.log("文件内容:", data);
});

3. Promise

javascript
const fs = require("fs").promises;

async function readFile() {
  try {
    const data = await fs.readFile("example.txt", "utf8");
    console.log("文件内容:", data);
  } catch (err) {
    console.error("读取文件失败:", err);
  }
}

readFile();

基础模块

1. 文件系统 (fs)

javascript
const fs = require("fs");

// 同步读取
try {
  const data = fs.readFileSync("file.txt", "utf8");
  console.log(data);
} catch (err) {
  console.error(err);
}

// 异步读取
fs.readFile("file.txt", "utf8", (err, data) => {
  if (err) throw err;
  console.log(data);
});

// Promise 方式
const fsPromises = require("fs").promises;
async function readFileAsync() {
  try {
    const data = await fsPromises.readFile("file.txt", "utf8");
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

2. 路径处理 (path)

javascript
const path = require("path");

// 路径拼接
console.log(path.join("/user", "files", "example.txt"));

// 获取绝对路径
console.log(path.resolve("example.txt"));

// 路径解析
console.log(path.parse("/user/files/example.txt"));

3. HTTP 模块

javascript
const http = require("http");

const server = http.createServer((req, res) => {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("Hello World\n");
});

server.listen(3000, () => {
  console.log("服务器运行在 http://localhost:3000/");
});

异步编程

1. Callback 方式

javascript
function fetchData(callback) {
  setTimeout(() => {
    callback(null, { data: "some data" });
  }, 1000);
}

fetchData((err, result) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(result);
});

2. Promise 方式

javascript
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ data: "some data" });
    }, 1000);
  });
}

fetchData()
  .then((result) => console.log(result))
  .catch((err) => console.error(err));

3. Async/Await 方式

javascript
async function getData() {
  try {
    const result = await fetchData();
    console.log(result);
  } catch (err) {
    console.error(err);
  }
}

getData();

模块系统

1. CommonJS 模块

javascript
// math.js
module.exports = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b,
};

// main.js
const math = require("./math");
console.log(math.add(2, 3));

2. ES 模块

javascript
// math.mjs
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// main.mjs
import { add, subtract } from "./math.mjs";
console.log(add(2, 3));

包管理

1. NPM 基础命令

bash
# 初始化项目
npm init

# 安装依赖
npm install express

# 安装开发依赖
npm install --save-dev nodemon

# 更新依赖
npm update

# 删除依赖
npm uninstall express

2. package.json

json
{
  "name": "my-node-app",
  "version": "1.0.0",
  "description": "My Node.js application",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.7",
    "jest": "^27.0.6"
  }
}

事件驱动编程

1. EventEmitter

javascript
const EventEmitter = require("events");

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

// 注册事件监听器
myEmitter.on("event", (arg) => {
  console.log("事件触发:", arg);
});

// 触发事件
myEmitter.emit("event", "自定义参数");

2. 自定义事件

javascript
class Database extends EventEmitter {
  query(sql) {
    // 模拟数据库查询
    setTimeout(() => {
      this.emit("result", { rows: [{ id: 1 }] });
    }, 1000);
  }
}

const db = new Database();

db.on("result", (result) => {
  console.log("查询结果:", result);
});

db.query("SELECT * FROM users");

文件系统操作

1. 文件读写

javascript
const fs = require("fs").promises;

async function fileOperations() {
  // 写入文件
  await fs.writeFile("test.txt", "你好,Node.js");

  // 读取文件
  const content = await fs.readFile("test.txt", "utf8");
  console.log("文件内容:", content);

  // 追加内容
  await fs.appendFile("test.txt", "\n新的一行");

  // 检查文件是否存在
  try {
    await fs.access("test.txt");
    console.log("文件存在");
  } catch {
    console.log("文件不存在");
  }
}

2. 目录操作

javascript
const fs = require("fs").promises;

async function directoryOperations() {
  // 创建目录
  await fs.mkdir("new-folder", { recursive: true });

  // 读取目录内容
  const files = await fs.readdir("new-folder");
  console.log("目录内容:", files);

  // 删除目录
  await fs.rmdir("new-folder");
}

网络编程

1. HTTP 服务器

javascript
const http = require("http");

const server = http.createServer((req, res) => {
  // 设置响应头
  res.setHeader("Content-Type", "application/json");

  // 路由处理
  if (req.url === "/api/users" && req.method === "GET") {
    res.statusCode = 200;
    res.end(JSON.stringify({ users: [] }));
  } else {
    res.statusCode = 404;
    res.end(JSON.stringify({ error: "Not Found" }));
  }
});

server.listen(3000, () => {
  console.log("服务器运行在 http://localhost:3000/");
});

2. WebSocket

javascript
const WebSocket = require("ws");

const wss = new WebSocket.Server({ port: 8080 });

wss.on("connection", (ws) => {
  console.log("新的连接");

  ws.on("message", (message) => {
    console.log("收到:", message);
    ws.send(`服务器收到: ${message}`);
  });

  ws.send("欢迎连接 WebSocket 服务器");
});

进程和线程

1. 子进程

javascript
const { spawn } = require("child_process");

// 执行系统命令
const ls = spawn("ls", ["-l"]);

ls.stdout.on("data", (data) => {
  console.log(`输出:${data}`);
});

ls.stderr.on("data", (data) => {
  console.error(`错误:${data}`);
});

ls.on("close", (code) => {
  console.log(`子进程退出码:${code}`);
});

2. 集群

javascript
const cluster = require("cluster");
const http = require("http");
const numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
  console.log(`主进程 ${process.pid} 正在运行`);

  // 衍生工作进程
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on("exit", (worker, code, signal) => {
    console.log(`工作进程 ${worker.process.pid} 已退出`);
  });
} else {
  // 工作进程可以共享任何 TCP 连接
  http
    .createServer((req, res) => {
      res.writeHead(200);
      res.end("你好世界\n");
    })
    .listen(8000);

  console.log(`工作进程 ${process.pid} 已启动`);
}

调试和性能优化

1. 调试

javascript
// 使用 debugger 语句
function calculate(x, y) {
  debugger;
  return x + y;
}

// 使用 console
console.log("普通日志");
console.error("错误日志");
console.warn("警告日志");
console.time("计时器");
console.timeEnd("计时器");

2. 性能监控

javascript
const { performance, PerformanceObserver } = require("perf_hooks");

// 创建性能观察器
const obs = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach((entry) => {
    console.log(`${entry.name}: ${entry.duration}`);
  });
});
obs.observe({ entryTypes: ["measure"] });

// 测量代码性能
performance.mark("A");
// 某些操作
performance.mark("B");
performance.measure("A to B", "A", "B");

最佳实践

1. 错误处理

javascript
// 全局错误处理
process.on("uncaughtException", (err) => {
  console.error("未捕获的异常:", err);
  // 执行清理操作
  process.exit(1);
});

process.on("unhandledRejection", (reason, promise) => {
  console.error("未处理的 Promise 拒绝:", reason);
});

// 异步错误处理
async function handleErrors() {
  try {
    await riskyOperation();
  } catch (err) {
    console.error("操作失败:", err);
    // 适当的错误处理
  }
}

2. 安全最佳实践

javascript
// 使用环境变量
require("dotenv").config();
const dbPassword = process.env.DB_PASSWORD;

// 输入验证
const validator = require("validator");
const userInput = "...";
if (!validator.isEmail(userInput)) {
  throw new Error("无效的邮箱地址");
}

// 安全的密码存储
const bcrypt = require("bcrypt");
const hashedPassword = await bcrypt.hash(password, 10);

3. 代码组织

javascript
// 模块化
// user/model.js
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }
}
module.exports = User;

// user/controller.js
const User = require("./model");
const UserService = require("./service");

class UserController {
  async createUser(req, res) {
    try {
      const user = await UserService.create(req.body);
      res.json(user);
    } catch (err) {
      res.status(400).json({ error: err.message });
    }
  }
}

4. 日志记录

javascript
const winston = require("winston");

const logger = winston.createLogger({
  level: "info",
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: "error.log", level: "error" }),
    new winston.transports.File({ filename: "combined.log" }),
  ],
});

// 记录日志
logger.info("应用启动");
logger.error("发生错误", { error: "database connection failed" });