第九章:Node.js应用场景实战

作者:Administrator 发布时间: 2026-03-13 阅读量:1 评论数:0

第九章:Node.js应用场景实战

9.1 Web服务器应用

// web-server.js
/**
 * Web服务器应用
 * 功能:提供用户管理的RESTful API
 */
​
const express = require('express');
const app = express();
const PORT = 3000;
​
app.use(express.json());
​
// 内存数据存储
const users = [];
let nextId = 1;
​
// 获取所有用户
app.get('/api/users', (req, res) => {
    res.json({ data: users });
});
​
// 获取单个用户
app.get('/api/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) {
        return res.status(404).json({ error: '用户不存在' });
    }
    res.json({ data: user });
});
​
// 创建用户
app.post('/api/users', (req, res) => {
    const { name, email } = req.body;
    const user = {
        id: nextId++,
        name,
        email,
        createdAt: new Date()
    };
    users.push(user);
    res.status(201).json({ data: user });
});
​
// 更新用户
app.put('/api/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) {
        return res.status(404).json({ error: '用户不存在' });
    }
    Object.assign(user, req.body);
    res.json({ data: user });
});
​
// 删除用户
app.delete('/api/users/:id', (req, res) => {
    const index = users.findIndex(u => u.id === parseInt(req.params.id));
    if (index === -1) {
        return res.status(404).json({ error: '用户不存在' });
    }
    users.splice(index, 1);
    res.json({ message: '删除成功' });
});
​
app.listen(PORT, () => {
    console.log(`服务器运行在 http://localhost:${PORT}`);
});

9.2 实时聊天应用

// chat-server.js
/**
 * 实时聊天服务器
 * 功能:多人在线聊天室
 * 技术:Socket.io
 */
​
const express = require('express');
const { createServer } = require('http');
const { Server } = require('socket.io');
​
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
    cors: { origin: '*' }
});
​
// 存储在线用户
const onlineUsers = new Map();
​
io.on('connection', (socket) => {
    console.log('用户连接:', socket.id);
    
    // 用户加入
    socket.on('join', (username) => {
        onlineUsers.set(socket.id, {
            id: socket.id,
            username,
            joinTime: new Date()
        });
        
        socket.broadcast.emit('userJoined', {
            username,
            message: `${username} 加入了聊天室`,
            onlineCount: onlineUsers.size
        });
        
        socket.emit('onlineUsers', Array.from(onlineUsers.values()));
    });
    
    // 接收消息
    socket.on('message', (data) => {
        const user = onlineUsers.get(socket.id);
        if (!user) return;
        
        const message = {
            id: Date.now(),
            username: user.username,
            content: data.content,
            timestamp: new Date()
        };
        
        io.emit('message', message);
    });
    
    // 用户断开
    socket.on('disconnect', () => {
        const user = onlineUsers.get(socket.id);
        if (user) {
            onlineUsers.delete(socket.id);
            socket.broadcast.emit('userLeft', {
                username: user.username,
                message: `${user.username} 离开了聊天室`,
                onlineCount: onlineUsers.size
            });
        }
    });
});
​
httpServer.listen(3000, () => {
    console.log('聊天服务器运行中');
});

9.3 命令行工具

// cli-tool.js
#!/usr/bin/env node
/**
 * 文件批量重命名工具
 * 用法: node cli-tool.js <目录> <模式>
 */
​
const fs = require('fs').promises;
const path = require('path');
​
async function renameFiles(dir, pattern) {
    const files = await fs.readdir(dir);
    let counter = 1;
    
    for (const file of files) {
        const oldPath = path.join(dir, file);
        const stat = await fs.stat(oldPath);
        
        if (stat.isFile()) {
            const ext = path.extname(file);
            const newName = pattern.replace('*', String(counter).padStart(3, '0')) + ext;
            const newPath = path.join(dir, newName);
            
            await fs.rename(oldPath, newPath);
            console.log(`${file} -> ${newName}`);
            counter++;
        }
    }
}
​
const [dir, pattern] = process.argv.slice(2);
if (!dir || !pattern) {
    console.log('用法: node cli-tool.js <目录> <模式>');
    process.exit(1);
}
​
renameFiles(dir, pattern).catch(console.error);

9.4 网络爬虫

// crawler.js
/**
 * 网页爬虫
 * 功能:抓取网页内容并提取数据
 */
​
const https = require('https');
const cheerio = require('cheerio');
​
// 发送HTTP请求
function fetch(url) {
    return new Promise((resolve, reject) => {
        https.get(url, (res) => {
            let data = '';
            res.on('data', chunk => data += chunk);
            res.on('end', () => resolve(data));
        }).on('error', reject);
    });
}
​
// 解析HTML并提取数据
async function crawl(url) {
    try {
        const html = await fetch(url);
        const $ = cheerio.load(html);
        
        const data = {
            title: $('title').text(),
            links: $('a').map((i, el) => $(el).attr('href')).get(),
            images: $('img').map((i, el) => $(el).attr('src')).get()
        };
        
        console.log('抓取结果:', data);
        return data;
        
    } catch (err) {
        console.error('抓取失败:', err);
    }
}
​
// 使用
crawl('https://example.com');

9.5 定时任务

// scheduler.js
/**
 * 定时任务调度器
 * 功能:定时执行特定任务
 */
​
const schedule = require('node-schedule');
​
// 每天凌晨执行
schedule.scheduleJob('0 0 * * *', () => {
    console.log('执行每日任务:', new Date());
    // 数据备份、清理等操作
});
​
// 每分钟执行
schedule.scheduleJob('*/1 * * * *', () => {
    console.log('执行分钟任务:', new Date());
});
​
// 特定时间执行
const date = new Date(2024, 0, 1, 0, 0, 0);
schedule.scheduleJob(date, () => {
    console.log('新年快乐!');
});
​
console.log('定时任务已启动');

9.6 文件处理服务

// file-service.js
/**
 * 文件上传处理服务
 * 功能:处理文件上传、压缩、转换
 */
​
const express = require('express');
const multer = require('multer');
const fs = require('fs').promises;
const path = require('path');
const sharp = require('sharp');
​
const app = express();
const upload = multer({ dest: 'uploads/' });
​
// 上传图片并生成缩略图
app.post('/upload', upload.single('image'), async (req, res) => {
    try {
        const inputPath = req.file.path;
        const outputDir = 'thumbnails/';
        
        // 确保目录存在
        await fs.mkdir(outputDir, { recursive: true });
        
        // 生成缩略图
        const thumbnailPath = path.join(outputDir, `thumb_${req.file.filename}.jpg`);
        await sharp(inputPath)
            .resize(200, 200)
            .toFile(thumbnailPath);
        
        res.json({
            original: inputPath,
            thumbnail: thumbnailPath
        });
        
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});
​
app.listen(3000);

评论