外观
node 后端基础
介绍
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,用于构建高性能、可扩展的网络应用程序。它采用事件驱动、非阻塞 I/O 模型,使得 JavaScript 能够脱离浏览器在服务器端运行。Node.js 的出现彻底改变了 JavaScript 只能在前端使用的局面,让开发者能够使用同一种语言开发全栈应用。
历史
Node.js 由 Ryan Dahl 于 2009 年创建,旨在解决传统 Web 服务器在处理高并发时的性能瓶颈。其核心创新在于将 Google 的 V8 JavaScript 引擎与事件循环机制结合,实现了高效的异步 I/O 处理。2010 年,npm 包管理器的推出极大促进了 Node.js 生态的发展。2015 年,Node.js 基金会成立,标志着项目的成熟和稳定。如今,Node.js 已成为全球最流行的后端技术之一。
核心架构
事件循环机制
Node.js 采用单线程事件循环模型,通过异步非阻塞方式处理并发请求:
请求到达 -> 事件循环接收 -> 分发给对应处理器 -> 非阻塞操作(如I/O)交给线程池
-> 事件循环继续处理其他请求 -> 操作完成 -> 回调函数执行 -> 返回响应模块系统
Node.js 使用 CommonJS 模块规范:
javascript
// 导入模块
const fs = require('fs')
// 导出模块
module.exports = { myFunction }核心特点
非阻塞 I/O
Node.js 使用异步操作处理 I/O 任务,不会阻塞主线程:
javascript
// 同步方式(阻塞)
const data = fs.readFileSync('file.txt') // 阻塞直到文件读取完成
console.log(data)
// 异步方式(非阻塞)
fs.readFile('file.txt', (err, data) => {
// 立即返回,完成后回调
if (err) throw err
console.log(data)
})事件驱动架构
基于观察者模式,通过 EventEmitter 实现事件处理:
javascript
const EventEmitter = require('events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
console.log('事件触发!')
})
myEmitter.emit('event')单线程与集群
Node.js 运行在单线程中,但可通过集群模式利用多核 CPU:
javascript
const cluster = require('cluster')
const os = require('os')
if (cluster.isMaster) {
// 主进程:fork工作进程
for (let i = 0; i < os.cpus().length; i++) {
cluster.fork()
}
} else {
// 工作进程:启动服务器
require('./server.js')
}跨平台支持
Node.js 可在 Windows、Linux、macOS 等主流操作系统上运行,提供一致的开发体验。
核心模块
HTTP 模块
创建 Web 服务器的核心模块:
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('服务器运行在 3000 端口')
})文件系统模块
提供文件操作功能,支持同步和异步两种方式:
javascript
const fs = require('fs')
// 异步文件读取
fs.readFile('/path/to/file', 'utf8', (err, data) => {
if (err) throw err
console.log(data)
})
// 文件写入
fs.writeFile('message.txt', 'Hello Node.js', (err) => {
if (err) throw err
console.log('文件已保存')
})路径处理模块
简化文件路径操作:
javascript
const path = require('path')
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..')
// 返回: '/foo/bar/baz/asdf'
path.resolve('/foo/bar', './baz')
// 返回: '/foo/bar/baz'事件模块
实现事件驱动编程的基础:
javascript
const EventEmitter = require('events')
class MyClass extends EventEmitter {
constructor() {
super()
}
doSomething() {
// 触发事件
this.emit('somethingHappened', { data: 'example' })
}
}包管理
npm 生态系统
Node.js 自带 npm (Node Package Manager),拥有全球最大的开源库生态系统:
项目初始化: npm init
安装包: npm install package-name
全局安装: npm install -g package-name
开发依赖: npm install --save-dev package-namepackage.json 文件
项目配置文件,定义依赖、脚本和元数据:
json
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"nodemon": "^2.0.0"
}
}异步编程
回调函数
传统的异步处理方式:
javascript
function readData(callback) {
fs.readFile('data.txt', 'utf8', (err, data) => {
if (err) return callback(err)
callback(null, data)
})
}Promise
更现代的异步解决方案:
javascript
function readFilePromise(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', (err, data) => {
if (err) reject(err)
else resolve(data)
})
})
}
readFilePromise('file.txt')
.then((data) => console.log(data))
.catch((err) => console.error(err))async/await
基于 Promise 的语法糖,使异步代码看起来像同步代码:
javascript
async function processFile() {
try {
const data = await readFilePromise('file.txt')
console.log(data)
} catch (error) {
console.error('读取文件失败:', error)
}
}Web 框架
Express.js
最流行的 Node.js Web 框架:
javascript
const express = require('express')
const app = express()
// 中间件
app.use(express.json())
// 路由
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.post('/users', (req, res) => {
const user = req.body
// 处理用户创建逻辑
res.status(201).json(user)
})
app.listen(3000, () => {
console.log('Express 服务器运行中')
})路由系统
组织 API 端点的结构化方式:
javascript
const router = express.Router()
router.get('/users', (req, res) => {
// 获取用户列表
})
router.get('/users/:id', (req, res) => {
const userId = req.params.id
// 获取特定用户
})
app.use('/api', router)数据库连接
MongoDB 连接
使用 Mongoose ODM:
javascript
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
const userSchema = new mongoose.Schema({
name: String,
email: String,
})
const User = mongoose.model('User', userSchema)
// 使用模型
const newUser = new User({ name: 'John', email: 'john@example.com' })
newUser.save()MySQL 连接
使用 mysql2 包:
javascript
const mysql = require('mysql2')
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
})
connection.execute(
'SELECT * FROM users WHERE id = ?',
[userId],
(err, results) => {
if (err) throw err
console.log(results)
}
)中间件
概念与使用
中间件是在请求和响应周期中执行的函数:
javascript
// 日志中间件
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`)
next() // 传递给下一个中间件
})
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('服务器错误!')
})常用中间件
javascript
// 解析 JSON 请求体
app.use(express.json())
// 解析 URL 编码请求体
app.use(express.urlencoded({ extended: true }))
// 静态文件服务
app.use(express.static('public'))
// CORS 跨域支持
app.use(require('cors')())错误处理
同步错误捕获
javascript
app.get('/dangerous', (req, res) => {
throw new Error('意外错误!')
})
// 错误处理中间件(必须放在最后)
app.use((err, req, res, next) => {
res.status(500).json({
error:
process.env.NODE_ENV === 'production' ? '服务器内部错误' : err.message,
})
})异步错误处理
javascript
// 使用 try/catch 与 async/await
app.get('/async-route', async (req, res, next) => {
try {
const data = await someAsyncOperation()
res.json(data)
} catch (error) {
next(error)
}
})配置管理
环境变量
使用 dotenv 管理环境相关配置:
javascript
require('dotenv').config()
const config = {
port: process.env.PORT || 3000,
db: {
host: process.env.DB_HOST || 'localhost',
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
},
jwtSecret: process.env.JWT_SECRET,
}配置结构化
javascript
// config.js
module.exports = {
development: {
database: 'myapp_dev',
logging: true,
},
production: {
database: 'myapp_prod',
logging: false,
},
}[process.env.NODE_ENV || 'development']部署与性能
进程管理
使用 PM2 管理 Node.js 进程:
bash
# 启动应用
pm2 start app.js
# 集群模式
pm2 start app.js -i max
# 监控
pm2 monit
# 重启应用
pm2 restart app性能优化策略
javascript
// 启用 gzip 压缩
const compression = require('compression')
app.use(compression())
// 设置缓存头
app.use(
express.static('public', {
maxAge: '1d',
})
)
// 数据库连接池
const pool = mysql.createPool({
connectionLimit: 10,
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
})健康检查
javascript
app.get('/health', (req, res) => {
res.json({
status: 'OK',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
})
})