Node.js之核心模块

Node.js之核心模块

fs 模块

fs (File System) 模块提供了与文件系统交互的 API,支持同步和异步操作。在服务端开发中,文件操作是核心功能之一。

常用方法

异步方法 (推荐)
  • fs.readFile(path, options, callback) - 异步读取文件
  • fs.writeFile(path, data, options, callback) - 异步写入文件
  • fs.appendFile(path, data, options, callback) - 异步追加文件
  • fs.unlink(path, callback) - 异步删除文件
  • fs.readdir(path, options, callback) - 异步读取目录
  • fs.mkdir(path, options, callback) - 异步创建目录
  • fs.stat(path, callback) - 异步获取文件信息
  • fs.access(path, mode, callback) - 异步检查文件访问权限
同步方法
  • fs.readFileSync(path, options) - 同步读取文件
  • fs.writeFileSync(path, data, options) - 同步写入文件
  • fs.appendFileSync(path, data, options) - 同步追加文件
  • fs.unlinkSync(path) - 同步删除文件
  • fs.readdirSync(path, options) - 同步读取目录
  • fs.mkdirSync(path, options) - 同步创建目录
Promise 方法 (Node.js 10+)
javascript 复制代码
const fs = require('fs').promises;
// 或者
const { promises: fs } = require('fs');

示例

异步读取文件

基本异步读取:

javascript 复制代码
const fs = require('fs');
const path = require('path');

// 回调风格异步读取
fs.readFile(path.join(__dirname, 'data.txt'), 'utf8', (err, data) => {
  if (err) {
    console.error('读取文件失败:', err.message);
    return;
  }
  console.log('文件内容:', data);
});

// Promise 风格异步读取
const fsPromises = require('fs').promises;

async function readFileExample() {
  try {
    const data = await fsPromises.readFile('config.json', 'utf8');
    const config = JSON.parse(data);
    console.log('配置信息:', config);
  } catch (error) {
    console.error('读取配置文件失败:', error.message);
  }
}

readFileExample();

// 流式读取大文件
const fs = require('fs');

function readLargeFile(filePath) {
  const readStream = fs.createReadStream(filePath, { 
    encoding: 'utf8',
    highWaterMark: 1024 // 1KB 缓冲区
  });

  readStream.on('data', (chunk) => {
    console.log('读取数据块:', chunk.length, '字节');
    // 处理数据块
  });

  readStream.on('end', () => {
    console.log('文件读取完成');
  });

  readStream.on('error', (err) => {
    console.error('读取失败:', err.message);
  });
}
同步写入文件

基本同步写入:

javascript 复制代码
const fs = require('fs');
const path = require('path');

try {
  // 写入字符串数据
  const content = 'Hello, Node.js!';
  fs.writeFileSync('output.txt', content, 'utf8');
  console.log('文件写入成功');

  // 写入 JSON 数据
  const userData = {
    name: 'Alice',
    age: 30,
    email: 'alice@example.com'
  };
  
  fs.writeFileSync('user.json', JSON.stringify(userData, null, 2), 'utf8');
  console.log('JSON 数据写入成功');

  // 追加内容到文件
  const logEntry = `${new Date().toISOString()} - 应用启动\n`;
  fs.appendFileSync('app.log', logEntry, 'utf8');
  console.log('日志追加成功');

} catch (error) {
  console.error('文件操作失败:', error.message);
}

// 批量文件操作示例
function batchFileOperations() {
  const files = ['file1.txt', 'file2.txt', 'file3.txt'];
  
  files.forEach((filename, index) => {
    try {
      const content = `这是第 ${index + 1} 个文件的内容`;
      fs.writeFileSync(filename, content, 'utf8');
      console.log(`${filename} 创建成功`);
    } catch (error) {
      console.error(`创建 ${filename} 失败:`, error.message);
    }
  });
}

batchFileOperations();

高级文件操作示例:

javascript 复制代码
const fs = require('fs');
const path = require('path');

class FileManager {
  constructor(basePath = './') {
    this.basePath = basePath;
  }

  async ensureDirectory(dirPath) {
    const fullPath = path.join(this.basePath, dirPath);
    try {
      await fs.promises.mkdir(fullPath, { recursive: true });
      return true;
    } catch (error) {
      console.error('创建目录失败:', error.message);
      return false;
    }
  }

  async writeJsonFile(filename, data) {
    try {
      const filePath = path.join(this.basePath, filename);
      const jsonString = JSON.stringify(data, null, 2);
      await fs.promises.writeFile(filePath, jsonString, 'utf8');
      return true;
    } catch (error) {
      console.error('写入 JSON 文件失败:', error.message);
      return false;
    }
  }

  async readJsonFile(filename) {
    try {
      const filePath = path.join(this.basePath, filename);
      const content = await fs.promises.readFile(filePath, 'utf8');
      return JSON.parse(content);
    } catch (error) {
      console.error('读取 JSON 文件失败:', error.message);
      return null;
    }
  }

  async copyFile(source, destination) {
    try {
      const sourcePath = path.join(this.basePath, source);
      const destPath = path.join(this.basePath, destination);
      await fs.promises.copyFile(sourcePath, destPath);
      return true;
    } catch (error) {
      console.error('复制文件失败:', error.message);
      return false;
    }
  }

  async getFileStats(filename) {
    try {
      const filePath = path.join(this.basePath, filename);
      const stats = await fs.promises.stat(filePath);
      return {
        size: stats.size,
        created: stats.birthtime,
        modified: stats.mtime,
        isFile: stats.isFile(),
        isDirectory: stats.isDirectory()
      };
    } catch (error) {
      console.error('获取文件信息失败:', error.message);
      return null;
    }
  }
}

// 使用示例
async function demonstrateFileManager() {
  const fileManager = new FileManager('./data');
  
  // 确保目录存在
  await fileManager.ensureDirectory('users');
  
  // 写入用户数据
  const userData = { name: 'Bob', age: 25 };
  await fileManager.writeJsonFile('users/bob.json', userData);
  
  // 读取用户数据
  const retrievedData = await fileManager.readJsonFile('users/bob.json');
  console.log('读取的用户数据:', retrievedData);
  
  // 获取文件信息
  const fileStats = await fileManager.getFileStats('users/bob.json');
  console.log('文件信息:', fileStats);
}

demonstrateFileManager();

文件操作流程图:

flowchart TD A[开始文件操作] --> B{选择操作类型} B -->|读取| C[检查文件是否存在] B -->|写入| D[检查目录是否存在] B -->|删除| E[检查文件权限] C -->|存在| F[选择读取方式] C -->|不存在| G[返回错误] F -->|同步| H[readFileSync] F -->|异步回调| I[readFile] F -->|Promise| J[fs.promises.readFile] F -->|流式| K[createReadStream] D -->|存在| L[执行写入操作] D -->|不存在| M[创建目录] M --> L L -->|成功| N[返回结果] L -->|失败| O[处理错误] E -->|有权限| P[执行删除] E -->|无权限| Q[权限错误] H --> N I --> N J --> N K --> N P --> N G --> R[错误处理] O --> R Q --> R R --> S[结束] N --> S

path 模块

path 模块提供了处理文件和目录路径的实用工具。它能够跨平台地处理路径,自动适配 Windows 和 Unix 系统的路径分隔符。

常用方法

路径操作方法
  • path.join(...paths) - 连接路径片段,自动处理分隔符
  • path.resolve(...paths) - 解析为绝对路径
  • path.relative(from, to) - 计算相对路径
  • path.dirname(path) - 获取目录名
  • path.basename(path, ext) - 获取文件名(可选移除扩展名)
  • path.extname(path) - 获取文件扩展名
  • path.normalize(path) - 规范化路径
路径属性
  • path.sep - 路径分隔符 (Unix: /, Windows: \)
  • path.delimiter - 环境变量路径分隔符 (Unix: :, Windows: ;)
路径解析方法
  • path.parse(path) - 解析路径为对象
  • path.format(pathObject) - 从对象构造路径
  • path.isAbsolute(path) - 判断是否为绝对路径

示例

基本路径操作:

javascript 复制代码
const path = require('path');

// 路径连接 - 推荐使用,自动处理分隔符
const filePath = path.join('/users', 'documents', 'project', 'index.js');
console.log(filePath); // Unix: /users/documents/project/index.js
                       // Windows: \users\documents\project\index.js

// 解析为绝对路径
const absolutePath = path.resolve('src', 'components', 'Button.js');
console.log(absolutePath); // /current/working/directory/src/components/Button.js

// 获取当前文件目录的绝对路径
const currentDir = path.resolve(__dirname);
console.log('当前目录:', currentDir);

// 路径规范化
const messyPath = '/users//documents/./project/../project/index.js';
const cleanPath = path.normalize(messyPath);
console.log(cleanPath); // /users/documents/project/index.js

// 计算相对路径
const from = '/users/alice/documents';
const to = '/users/alice/pictures/photo.jpg';
const relativePath = path.relative(from, to);
console.log(relativePath); // ../pictures/photo.jpg

文件路径解析:

javascript 复制代码
const path = require('path');

const filePath = '/users/documents/project/src/components/Button.jsx';

// 获取目录名
const directory = path.dirname(filePath);
console.log('目录:', directory); // /users/documents/project/src/components

// 获取文件名(包含扩展名)
const filename = path.basename(filePath);
console.log('文件名:', filename); // Button.jsx

// 获取文件名(不含扩展名)
const filenameWithoutExt = path.basename(filePath, path.extname(filePath));
console.log('文件名(无扩展名):', filenameWithoutExt); // Button

// 获取扩展名
const extension = path.extname(filePath);
console.log('扩展名:', extension); // .jsx

// 解析路径为对象
const pathObject = path.parse(filePath);
console.log('路径对象:', pathObject);
/*
{
  root: '/',
  dir: '/users/documents/project/src/components',
  base: 'Button.jsx',
  ext: '.jsx',
  name: 'Button'
}
*/

// 从对象构造路径
const reconstructedPath = path.format({
  dir: '/users/documents/project/src/components',
  name: 'Button',
  ext: '.jsx'
});
console.log('重构路径:', reconstructedPath); // /users/documents/project/src/components/Button.jsx

// 判断是否为绝对路径
console.log('是否为绝对路径:', path.isAbsolute(filePath)); // true
console.log('是否为绝对路径:', path.isAbsolute('./src/Button.jsx')); // false

实际项目应用示例:

javascript 复制代码
const path = require('path');
const fs = require('fs');

class ProjectManager {
  constructor(projectRoot) {
    this.projectRoot = path.resolve(projectRoot);
    this.srcDir = path.join(this.projectRoot, 'src');
    this.buildDir = path.join(this.projectRoot, 'build');
    this.configDir = path.join(this.projectRoot, 'config');
  }

  // 获取源文件的完整路径
  getSourcePath(relativePath) {
    return path.join(this.srcDir, relativePath);
  }

  // 获取构建输出路径
  getBuildPath(sourcePath) {
    const relativePath = path.relative(this.srcDir, sourcePath);
    const parsedPath = path.parse(relativePath);
    
    // 将 .jsx/.tsx 转换为 .js
    if (['.jsx', '.tsx'].includes(parsedPath.ext)) {
      parsedPath.ext = '.js';
      parsedPath.base = parsedPath.name + parsedPath.ext;
    }
    
    return path.join(this.buildDir, path.format(parsedPath));
  }

  // 扫描指定目录下的文件
  async scanFiles(directory, extensions = ['.js', '.jsx', '.ts', '.tsx']) {
    const files = [];
    const fullPath = path.resolve(this.projectRoot, directory);
    
    try {
      const items = await fs.promises.readdir(fullPath, { withFileTypes: true });
      
      for (const item of items) {
        const itemPath = path.join(fullPath, item.name);
        
        if (item.isDirectory()) {
          // 递归扫描子目录
          const subFiles = await this.scanFiles(path.relative(this.projectRoot, itemPath), extensions);
          files.push(...subFiles);
        } else if (item.isFile()) {
          const ext = path.extname(item.name);
          if (extensions.includes(ext)) {
            files.push({
              path: itemPath,
              relativePath: path.relative(this.projectRoot, itemPath),
              name: path.basename(item.name, ext),
              ext: ext
            });
          }
        }
      }
    } catch (error) {
      console.error(`扫描目录失败 ${directory}:`, error.message);
    }
    
    return files;
  }

  // 创建必要的项目目录
  async createDirectories() {
    const dirs = [this.srcDir, this.buildDir, this.configDir];
    
    for (const dir of dirs) {
      try {
        await fs.promises.mkdir(dir, { recursive: true });
        console.log(`目录已创建: ${path.relative(process.cwd(), dir)}`);
      } catch (error) {
        console.error(`创建目录失败 ${dir}:`, error.message);
      }
    }
  }

  // 获取相对于项目根目录的路径
  getRelativeToProject(filePath) {
    return path.relative(this.projectRoot, filePath);
  }

  // 检查文件是否在项目范围内
  isInProject(filePath) {
    const relativePath = path.relative(this.projectRoot, filePath);
    return !relativePath.startsWith('..') && !path.isAbsolute(relativePath);
  }
}

// 使用示例
async function demonstrateProjectManager() {
  const project = new ProjectManager('./my-react-app');
  
  // 创建项目目录结构
  await project.createDirectories();
  
  // 获取源文件路径
  const componentPath = project.getSourcePath('components/Button.jsx');
  console.log('组件路径:', componentPath);
  
  // 获取对应的构建路径
  const buildPath = project.getBuildPath(componentPath);
  console.log('构建路径:', buildPath);
  
  // 扫描源文件
  const sourceFiles = await project.scanFiles('src');
  console.log('源文件列表:', sourceFiles);
  
  // 检查文件是否在项目范围内
  console.log('是否在项目内:', project.isInProject(componentPath));
}

demonstrateProjectManager();

跨平台路径处理:

javascript 复制代码
const path = require('path');

// 处理不同操作系统的路径
function createCrossPlatformPath(...segments) {
  return path.join(...segments);
}

// 配置管理器
class ConfigManager {
  constructor() {
    this.configPaths = {
      // 用户配置目录
      user: path.join(require('os').homedir(), '.myapp'),
      // 应用配置目录
      app: path.join(__dirname, '..', 'config'),
      // 临时目录
      temp: path.join(require('os').tmpdir(), 'myapp')
    };
  }

  getConfigPath(type, filename) {
    if (!this.configPaths[type]) {
      throw new Error(`未知的配置类型: ${type}`);
    }
    
    return filename 
      ? path.join(this.configPaths[type], filename)
      : this.configPaths[type];
  }

  // 确保配置目录存在
  async ensureConfigDirs() {
    const fs = require('fs').promises;
    
    for (const [type, dirPath] of Object.entries(this.configPaths)) {
      try {
        await fs.mkdir(dirPath, { recursive: true });
        console.log(`${type} 配置目录已就绪: ${dirPath}`);
      } catch (error) {
        console.error(`创建 ${type} 配置目录失败:`, error.message);
      }
    }
  }
}

// 使用示例
const configManager = new ConfigManager();

// 获取用户配置文件路径
const userConfigPath = configManager.getConfigPath('user', 'settings.json');
console.log('用户配置路径:', userConfigPath);

// 获取应用配置文件路径
const appConfigPath = configManager.getConfigPath('app', 'database.json');
console.log('应用配置路径:', appConfigPath);

// 确保配置目录存在
configManager.ensureConfigDirs();

os模块

os 模块提供了与操作系统相关的实用工具函数,可以获取系统信息、资源使用情况等。这对于系统监控、性能调优和跨平台兼容性非常重要。

常用方法

系统信息方法
  • os.platform() - 获取操作系统平台 ('darwin', 'linux', 'win32')
  • os.type() - 获取操作系统名称
  • os.arch() - 获取 CPU 架构 ('x64', 'arm64', 'ia32')
  • os.release() - 获取操作系统版本
  • os.hostname() - 获取主机名
  • os.endianness() - 获取字节序 ('BE' 或 'LE')
系统资源方法
  • os.totalmem() - 获取总内存(字节)
  • os.freemem() - 获取可用内存(字节)
  • os.cpus() - 获取 CPU 信息数组
  • os.loadavg() - 获取系统负载平均值
  • os.uptime() - 获取系统运行时间(秒)
用户和目录方法
  • os.homedir() - 获取用户主目录
  • os.tmpdir() - 获取临时目录
  • os.userInfo([options]) - 获取当前用户信息
网络接口方法
  • os.networkInterfaces() - 获取网络接口信息

示例

基本系统信息获取:

javascript 复制代码
const os = require('os');

// 系统基本信息
console.log('操作系统平台:', os.platform());     // darwin, linux, win32
console.log('操作系统类型:', os.type());         // Darwin, Linux, Windows_NT
console.log('CPU 架构:', os.arch());             // x64, arm64, ia32
console.log('操作系统版本:', os.release());      // 21.6.0
console.log('主机名:', os.hostname());           // MacBook-Pro.local
console.log('字节序:', os.endianness());         // LE (小端序)

// 系统运行时间
const uptime = os.uptime();
const days = Math.floor(uptime / (24 * 3600));
const hours = Math.floor((uptime % (24 * 3600)) / 3600);
const minutes = Math.floor((uptime % 3600) / 60);
console.log(`系统运行时间: ${days}天 ${hours}小时 ${minutes}分钟`);

// 用户信息
const userInfo = os.userInfo();
console.log('当前用户:', userInfo);
/*
{
  uid: 501,
  gid: 20,
  username: 'alice',
  homedir: '/Users/alice',
  shell: '/bin/zsh'
}
*/

// 目录信息
console.log('用户主目录:', os.homedir());        // /Users/alice
console.log('临时目录:', os.tmpdir());           // /tmp

系统资源监控:

javascript 复制代码
const os = require('os');

// 内存信息
function getMemoryInfo() {
  const totalMem = os.totalmem();
  const freeMem = os.freemem();
  const usedMem = totalMem - freeMem;
  const memoryUsagePercent = (usedMem / totalMem * 100).toFixed(2);

  return {
    total: Math.round(totalMem / 1024 / 1024 / 1024 * 100) / 100, // GB
    free: Math.round(freeMem / 1024 / 1024 / 1024 * 100) / 100,   // GB
    used: Math.round(usedMem / 1024 / 1024 / 1024 * 100) / 100,   // GB
    usagePercent: memoryUsagePercent
  };
}

const memInfo = getMemoryInfo();
console.log('内存信息:', memInfo);

// CPU 信息
function getCpuInfo() {
  const cpus = os.cpus();
  const cpuCount = cpus.length;
  const cpuModel = cpus[0].model;
  const cpuSpeed = cpus[0].speed;

  // 计算 CPU 使用率(简化版本)
  let totalIdle = 0;
  let totalTick = 0;
  
  cpus.forEach(cpu => {
    for (let type in cpu.times) {
      totalTick += cpu.times[type];
    }
    totalIdle += cpu.times.idle;
  });
  
  const idlePercent = (totalIdle / totalTick * 100).toFixed(2);
  const usagePercent = (100 - idlePercent).toFixed(2);

  return {
    count: cpuCount,
    model: cpuModel,
    speed: cpuSpeed,
    usage: usagePercent,
    idle: idlePercent
  };
}

const cpuInfo = getCpuInfo();
console.log('CPU 信息:', cpuInfo);

// 系统负载 (Unix/Linux 系统)
if (os.platform() !== 'win32') {
  const loadAvg = os.loadavg();
  console.log('系统负载 (1分钟, 5分钟, 15分钟):', loadAvg);
}

实际应用 - 系统监控器:

javascript 复制代码
const os = require('os');

class SystemMonitor {
  constructor(interval = 5000) {
    this.interval = interval;
    this.isMonitoring = false;
    this.monitorTimer = null;
  }

  // 获取完整的系统状态
  getSystemStatus() {
    const platform = os.platform();
    const memory = this.getMemoryStatus();
    const cpu = this.getCpuStatus();
    const network = this.getNetworkInterfaces();

    return {
      timestamp: new Date().toISOString(),
      platform: platform,
      hostname: os.hostname(),
      uptime: os.uptime(),
      memory: memory,
      cpu: cpu,
      network: network,
      loadavg: platform !== 'win32' ? os.loadavg() : null
    };
  }

  getMemoryStatus() {
    const total = os.totalmem();
    const free = os.freemem();
    const used = total - free;

    return {
      total: total,
      free: free,
      used: used,
      usagePercent: Number((used / total * 100).toFixed(2)),
      totalGB: Number((total / 1024 / 1024 / 1024).toFixed(2)),
      freeGB: Number((free / 1024 / 1024 / 1024).toFixed(2)),
      usedGB: Number((used / 1024 / 1024 / 1024).toFixed(2))
    };
  }

  getCpuStatus() {
    const cpus = os.cpus();
    const cpuCount = cpus.length;
    
    // 计算总的 CPU 时间
    let totalUser = 0;
    let totalNice = 0;
    let totalSys = 0;
    let totalIdle = 0;
    let totalIrq = 0;
    
    cpus.forEach(cpu => {
      totalUser += cpu.times.user;
      totalNice += cpu.times.nice || 0;
      totalSys += cpu.times.sys;
      totalIdle += cpu.times.idle;
      totalIrq += cpu.times.irq || 0;
    });
    
    const totalTime = totalUser + totalNice + totalSys + totalIdle + totalIrq;
    
    return {
      count: cpuCount,
      model: cpus[0].model,
      speed: cpus[0].speed,
      usage: {
        user: Number((totalUser / totalTime * 100).toFixed(2)),
        system: Number((totalSys / totalTime * 100).toFixed(2)),
        idle: Number((totalIdle / totalTime * 100).toFixed(2)),
        total: Number(((totalTime - totalIdle) / totalTime * 100).toFixed(2))
      }
    };
  }

  getNetworkInterfaces() {
    const interfaces = os.networkInterfaces();
    const result = {};
    
    for (const [name, addresses] of Object.entries(interfaces)) {
      result[name] = addresses
        .filter(addr => !addr.internal)
        .map(addr => ({
          address: addr.address,
          family: addr.family,
          mac: addr.mac
        }));
    }
    
    return result;
  }

  // 检查系统健康状态
  checkSystemHealth() {
    const status = this.getSystemStatus();
    const warnings = [];
    
    // 内存使用率检查
    if (status.memory.usagePercent > 90) {
      warnings.push(`内存使用率过高: ${status.memory.usagePercent}%`);
    }
    
    // CPU 使用率检查
    if (status.cpu.usage.total > 90) {
      warnings.push(`CPU 使用率过高: ${status.cpu.usage.total}%`);
    }
    
    // 磁盘可用内存检查
    if (status.memory.freeGB < 1) {
      warnings.push(`可用内存不足: ${status.memory.freeGB}GB`);
    }
    
    // 系统负载检查 (Unix/Linux)
    if (status.loadavg && status.loadavg[0] > status.cpu.count * 2) {
      warnings.push(`系统负载过高: ${status.loadavg[0].toFixed(2)}`);
    }
    
    return {
      status: warnings.length === 0 ? 'healthy' : 'warning',
      warnings: warnings,
      systemInfo: status
    };
  }

  // 开始监控
  startMonitoring(callback) {
    if (this.isMonitoring) {
      console.log('监控已在运行中');
      return;
    }
    
    this.isMonitoring = true;
    console.log(`开始系统监控,间隔 ${this.interval}ms`);
    
    const monitor = () => {
      const healthCheck = this.checkSystemHealth();
      
      if (callback) {
        callback(healthCheck);
      } else {
        console.log(`[${healthCheck.systemInfo.timestamp}] 系统状态: ${healthCheck.status}`);
        if (healthCheck.warnings.length > 0) {
          console.warn('⚠️  警告:', healthCheck.warnings);
        }
      }
      
      if (this.isMonitoring) {
        this.monitorTimer = setTimeout(monitor, this.interval);
      }
    };
    
    monitor();
  }

  // 停止监控
  stopMonitoring() {
    this.isMonitoring = false;
    if (this.monitorTimer) {
      clearTimeout(this.monitorTimer);
      this.monitorTimer = null;
    }
    console.log('系统监控已停止');
  }

  // 生成系统报告
  generateReport() {
    const status = this.getSystemStatus();
    const report = `
=== 系统监控报告 ===
时间: ${status.timestamp}
主机: ${status.hostname}
平台: ${status.platform}
运行时间: ${Math.floor(status.uptime / 3600)}小时

内存使用:
- 总计: ${status.memory.totalGB}GB
- 已用: ${status.memory.usedGB}GB (${status.memory.usagePercent}%)
- 可用: ${status.memory.freeGB}GB

CPU 信息:
- 型号: ${status.cpu.model}
- 核心数: ${status.cpu.count}
- 使用率: ${status.cpu.usage.total}%
${status.loadavg ? `- 负载: ${status.loadavg[0].toFixed(2)}` : ''}

网络接口:
${Object.entries(status.network).map(([name, addrs]) => 
  `- ${name}: ${addrs.map(addr => addr.address).join(', ')}`
).join('\n')}
===================
    `;
    
    return report;
  }
}

// 使用示例
const monitor = new SystemMonitor(5000);

// 获取一次性系统状态
console.log('当前系统状态:');
console.log(monitor.checkSystemHealth());

// 生成详细报告
console.log(monitor.generateReport());

// 开始持续监控
monitor.startMonitoring((healthCheck) => {
  if (healthCheck.status === 'warning') {
    console.warn('🚨 系统警告:', healthCheck.warnings);
  }
});

// 10秒后停止监控
setTimeout(() => {
  monitor.stopMonitoring();
}, 10000);

跨平台兼容性处理:

javascript 复制代码
const os = require('os');

class CrossPlatformUtils {
  static getPlatformInfo() {
    const platform = os.platform();
    const isWindows = platform === 'win32';
    const isMac = platform === 'darwin';
    const isLinux = platform === 'linux';
    
    return {
      platform,
      isWindows,
      isMac,
      isLinux,
      pathSeparator: isWindows ? '\\' : '/',
      lineEnding: isWindows ? '\r\n' : '\n'
    };
  }

  static getExecutablePath(name) {
    const { isWindows } = this.getPlatformInfo();
    return isWindows ? `${name}.exe` : name;
  }

  static getConfigDir(appName) {
    const platform = os.platform();
    const homeDir = os.homedir();
    
    switch (platform) {
      case 'win32':
        return process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming', appName);
      case 'darwin':
        return path.join(homeDir, 'Library', 'Application Support', appName);
      default:
        return path.join(homeDir, `.${appName.toLowerCase()}`);
    }
  }
}

// 使用示例
const platformInfo = CrossPlatformUtils.getPlatformInfo();
console.log('平台信息:', platformInfo);

const configDir = CrossPlatformUtils.getConfigDir('MyApp');
console.log('配置目录:', configDir);

process 模块

process 模块是一个全局对象,提供了当前 Node.js 进程的信息和控制方法。它不需要 require 即可使用,是 Node.js 应用程序与运行环境交互的重要接口。

常用属性与方法

进程信息属性
  • process.pid - 当前进程的 PID
  • process.ppid - 父进程的 PID
  • process.platform - 操作系统平台
  • process.arch - CPU 架构
  • process.version - Node.js 版本
  • process.versions - Node.js 及其依赖的版本信息
  • process.uptime() - 进程运行时间(秒)
命令行参数和环境变量
  • process.argv - 命令行参数数组
  • process.env - 环境变量对象
  • process.cwd() - 当前工作目录
  • process.chdir(directory) - 改变工作目录
进程控制方法
  • process.exit([code]) - 退出进程
  • process.kill(pid, [signal]) - 发送信号给进程
  • process.abort() - 立即终止进程
  • process.nextTick(callback) - 在下一个事件循环执行回调
事件和流
  • process.stdin - 标准输入流
  • process.stdout - 标准输出流
  • process.stderr - 标准错误流
内存和资源
  • process.memoryUsage() - 内存使用情况
  • process.cpuUsage([previousValue]) - CPU 使用情况
  • process.hrtime([time]) - 高精度时间

示例

获取命令行参数

基本参数解析:

javascript 复制代码
// 运行命令: node app.js --port 3000 --env production --verbose
console.log('完整参数列表:', process.argv);
/*
[
  '/usr/local/bin/node',     // Node.js 执行路径
  '/path/to/app.js',         // 脚本文件路径
  '--port',                  // 用户参数开始
  '3000',
  '--env', 
  'production',
  '--verbose'
]
*/

// 获取用户传入的参数(去除前两个系统参数)
const userArgs = process.argv.slice(2);
console.log('用户参数:', userArgs); // ['--port', '3000', '--env', 'production', '--verbose']

// 简单的参数解析器
function parseArgs(args) {
  const parsed = {};
  const flags = [];
  
  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    
    if (arg.startsWith('--')) {
      const key = arg.slice(2);
      const nextArg = args[i + 1];
      
      // 如果下一个参数不是选项,则作为值
      if (nextArg && !nextArg.startsWith('--')) {
        parsed[key] = nextArg;
        i++; // 跳过下一个参数
      } else {
        // 否则作为标志
        flags.push(key);
      }
    } else if (arg.startsWith('-')) {
      // 短选项处理
      const key = arg.slice(1);
      flags.push(key);
    }
  }
  
  return { options: parsed, flags };
}

const { options, flags } = parseArgs(userArgs);
console.log('解析结果:');
console.log('选项:', options);     // { port: '3000', env: 'production' }
console.log('标志:', flags);       // ['verbose']

// 高级参数解析器类
class ArgumentParser {
  constructor() {
    this.options = {};
    this.flags = new Set();
    this.requiredOptions = new Set();
    this.defaults = {};
  }
  
  addOption(name, options = {}) {
    if (options.required) {
      this.requiredOptions.add(name);
    }
    if (options.default !== undefined) {
      this.defaults[name] = options.default;
    }
    return this;
  }
  
  addFlag(name) {
    this.flags.add(name);
    return this;
  }
  
  parse(args = process.argv.slice(2)) {
    const result = { ...this.defaults };
    const foundFlags = new Set();
    
    for (let i = 0; i < args.length; i++) {
      const arg = args[i];
      
      if (arg.startsWith('--')) {
        const key = arg.slice(2);
        
        if (this.flags.has(key)) {
          foundFlags.add(key);
        } else {
          const nextArg = args[i + 1];
          if (nextArg && !nextArg.startsWith('-')) {
            result[key] = this.parseValue(nextArg);
            i++;
          } else {
            result[key] = true;
          }
        }
      }
    }
    
    // 检查必需选项
    for (const required of this.requiredOptions) {
      if (result[required] === undefined) {
        throw new Error(`缺少必需选项: --${required}`);
      }
    }
    
    result._flags = foundFlags;
    return result;
  }
  
  parseValue(value) {
    // 尝试解析为数字
    if (/^\d+$/.test(value)) {
      return parseInt(value, 10);
    }
    if (/^\d*\.\d+$/.test(value)) {
      return parseFloat(value);
    }
    // 解析布尔值
    if (value === 'true') return true;
    if (value === 'false') return false;
    
    return value;
  }
}

// 使用示例
const parser = new ArgumentParser()
  .addOption('port', { default: 3000 })
  .addOption('host', { default: 'localhost' })
  .addOption('env', { required: true })
  .addFlag('verbose')
  .addFlag('debug');

try {
  const config = parser.parse();
  console.log('应用配置:', config);
  
  if (config._flags.has('verbose')) {
    console.log('详细模式已启用');
  }
} catch (error) {
  console.error('参数解析错误:', error.message);
  process.exit(1);
}
退出进程

优雅退出处理:

javascript 复制代码
// 基本的进程退出
function basicExit() {
  console.log('准备退出进程...');
  process.exit(0); // 0 表示成功,非0表示错误
}

// 优雅的进程退出处理器
class GracefulShutdown {
  constructor() {
    this.shutdownTasks = [];
    this.shutdownTimeout = 10000; // 10秒超时
    this.isShuttingDown = false;
    
    this.setupSignalHandlers();
  }
  
  // 添加关闭任务
  addTask(name, handler) {
    this.shutdownTasks.push({ name, handler });
    return this;
  }
  
  // 设置关闭超时
  setTimeout(ms) {
    this.shutdownTimeout = ms;
    return this;
  }
  
  // 设置信号处理器
  setupSignalHandlers() {
    // 处理 Ctrl+C (SIGINT)
    process.on('SIGINT', () => {
      console.log('\n收到 SIGINT 信号,开始优雅关闭...');
      this.shutdown('SIGINT');
    });
    
    // 处理终止信号 (SIGTERM)
    process.on('SIGTERM', () => {
      console.log('收到 SIGTERM 信号,开始优雅关闭...');
      this.shutdown('SIGTERM');
    });
    
    // 处理未捕获的异常
    process.on('uncaughtException', (error) => {
      console.error('未捕获的异常:', error);
      this.shutdown('UNCAUGHT_EXCEPTION', 1);
    });
    
    // 处理未处理的 Promise 拒绝
    process.on('unhandledRejection', (reason, promise) => {
      console.error('未处理的 Promise 拒绝:', reason);
      console.error('位置:', promise);
      this.shutdown('UNHANDLED_REJECTION', 1);
    });
  }
  
  async shutdown(signal, exitCode = 0) {
    if (this.isShuttingDown) {
      console.log('关闭进程中,请稍等...');
      return;
    }
    
    this.isShuttingDown = true;
    console.log(`开始优雅关闭进程 (信号: ${signal})`);
    
    // 设置超时强制退出
    const timeoutId = setTimeout(() => {
      console.error(`关闭超时 (${this.shutdownTimeout}ms),强制退出`);
      process.exit(1);
    }, this.shutdownTimeout);
    
    try {
      // 执行所有关闭任务
      for (const task of this.shutdownTasks) {
        console.log(`执行关闭任务: ${task.name}`);
        try {
          await task.handler();
          console.log(`✓ 任务 ${task.name} 完成`);
        } catch (error) {
          console.error(`✗ 任务 ${task.name} 失败:`, error.message);
        }
      }
      
      clearTimeout(timeoutId);
      console.log('所有关闭任务完成,退出进程');
      process.exit(exitCode);
      
    } catch (error) {
      console.error('关闭过程中出现错误:', error);
      clearTimeout(timeoutId);
      process.exit(1);
    }
  }
}

// 使用示例
const shutdown = new GracefulShutdown()
  .setTimeout(15000) // 15秒超时
  .addTask('关闭数据库连接', async () => {
    // 模拟关闭数据库
    await new Promise(resolve => setTimeout(resolve, 1000));
    console.log('数据库连接已关闭');
  })
  .addTask('清理临时文件', async () => {
    // 模拟清理工作
    await new Promise(resolve => setTimeout(resolve, 500));
    console.log('临时文件已清理');
  })
  .addTask('保存状态', async () => {
    // 模拟状态保存
    await new Promise(resolve => setTimeout(resolve, 300));
    console.log('应用状态已保存');
  });

console.log('应用启动完成,按 Ctrl+C 测试优雅关闭');

// 模拟长运行的应用
const interval = setInterval(() => {
  console.log(`应用运行中... PID: ${process.pid}`);
}, 2000);

// 清理定时器任务
shutdown.addTask('停止定时器', async () => {
  clearInterval(interval);
  console.log('定时器已停止');
});
读取环境变量

环境变量管理:

javascript 复制代码
// 基本环境变量读取
console.log('Node.js 版本:', process.env.NODE_ENV || '未设置');
console.log('用户路径:', process.env.PATH);
console.log('用户主目录:', process.env.HOME || process.env.USERPROFILE);

// 带默认值的环境变量读取
function getEnv(key, defaultValue = '') {
  return process.env[key] || defaultValue;
}

const config = {
  port: parseInt(getEnv('PORT', '3000')),
  host: getEnv('HOST', 'localhost'),
  nodeEnv: getEnv('NODE_ENV', 'development'),
  dbUrl: getEnv('DATABASE_URL', 'mongodb://localhost:27017/myapp'),
  jwtSecret: getEnv('JWT_SECRET'),
  logLevel: getEnv('LOG_LEVEL', 'info')
};

console.log('应用配置:', config);

// 高级环境变量管理器
class EnvManager {
  constructor(options = {}) {
    this.requiredVars = new Set();
    this.defaults = {};
    this.transforms = {};
    this.validations = {};
    this.prefix = options.prefix || '';
  }
  
  // 定义必需的环境变量
  required(name, options = {}) {
    const key = this.prefix + name;
    this.requiredVars.add(key);
    
    if (options.default !== undefined) {
      this.defaults[key] = options.default;
    }
    
    if (options.transform) {
      this.transforms[key] = options.transform;
    }
    
    if (options.validate) {
      this.validations[key] = options.validate;
    }
    
    return this;
  }
  
  // 定义可选的环境变量
  optional(name, defaultValue, options = {}) {
    const key = this.prefix + name;
    this.defaults[key] = defaultValue;
    
    if (options.transform) {
      this.transforms[key] = options.transform;
    }
    
    if (options.validate) {
      this.validations[key] = options.validate;
    }
    
    return this;
  }
  
  // 解析并验证环境变量
  parse() {
    const result = {};
    const errors = [];
    
    // 检查必需变量
    for (const key of this.requiredVars) {
      if (process.env[key] === undefined && this.defaults[key] === undefined) {
        errors.push(`缺少必需的环境变量: ${key}`);
      }
    }
    
    if (errors.length > 0) {
      throw new Error('环境变量验证失败:\n' + errors.join('\n'));
    }
    
    // 处理所有定义的变量
    const allKeys = new Set([...this.requiredVars, ...Object.keys(this.defaults)]);
    
    for (const key of allKeys) {
      let value = process.env[key];
      
      // 使用默认值
      if (value === undefined) {
        value = this.defaults[key];
      }
      
      // 应用转换
      if (this.transforms[key] && value !== undefined) {
        try {
          value = this.transforms[key](value);
        } catch (error) {
          errors.push(`环境变量 ${key} 转换失败: ${error.message}`);
          continue;
        }
      }
      
      // 验证
      if (this.validations[key] && value !== undefined) {
        try {
          if (!this.validations[key](value)) {
            errors.push(`环境变量 ${key} 验证失败`);
            continue;
          }
        } catch (error) {
          errors.push(`环境变量 ${key} 验证出错: ${error.message}`);
          continue;
        }
      }
      
      // 移除前缀
      const resultKey = key.replace(this.prefix, '');
      result[resultKey] = value;
    }
    
    if (errors.length > 0) {
      throw new Error('环境变量处理失败:\n' + errors.join('\n'));
    }
    
    return result;
  }
}

// 常用转换函数
const transforms = {
  int: (value) => {
    const num = parseInt(value, 10);
    if (isNaN(num)) throw new Error('不是有效的整数');
    return num;
  },
  
  float: (value) => {
    const num = parseFloat(value);
    if (isNaN(num)) throw new Error('不是有效的浮点数');
    return num;
  },
  
  bool: (value) => {
    if (typeof value === 'boolean') return value;
    const str = value.toLowerCase();
    if (['true', '1', 'yes', 'on'].includes(str)) return true;
    if (['false', '0', 'no', 'off'].includes(str)) return false;
    throw new Error('不是有效的布尔值');
  },
  
  array: (separator = ',') => (value) => {
    return value.split(separator).map(item => item.trim()).filter(Boolean);
  },
  
  json: (value) => {
    try {
      return JSON.parse(value);
    } catch (error) {
      throw new Error('不是有效的JSON');
    }
  }
};

// 常用验证函数
const validations = {
  port: (value) => value >= 1 && value <= 65535,
  url: (value) => /^https?:\/\/.+/.test(value),
  email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
  nonEmpty: (value) => value && value.length > 0
};

// 使用示例
try {
  const env = new EnvManager({ prefix: 'APP_' })
    .required('PORT', { 
      default: 3000, 
      transform: transforms.int,
      validate: validations.port 
    })
    .required('DATABASE_URL', { 
      validate: validations.nonEmpty 
    })
    .optional('DEBUG', false, { 
      transform: transforms.bool 
    })
    .optional('ALLOWED_ORIGINS', ['http://localhost:3000'], {
      transform: transforms.array()
    })
    .optional('JWT_SECRET', 'default-secret-key')
    .parse();

  console.log('解析的环境配置:', env);

} catch (error) {
  console.error(error.message);
  process.exit(1);
}

// 进程信息监控
function monitorProcess() {
  const startTime = Date.now();
  
  setInterval(() => {
    const memUsage = process.memoryUsage();
    const cpuUsage = process.cpuUsage();
    const uptime = process.uptime();
    
    console.log('\n=== 进程监控信息 ===');
    console.log(`PID: ${process.pid}`);
    console.log(`运行时间: ${Math.floor(uptime)}秒`);
    console.log(`内存使用:`);
    console.log(`  - RSS: ${Math.round(memUsage.rss / 1024 / 1024)}MB`);
    console.log(`  - Heap Used: ${Math.round(memUsage.heapUsed / 1024 / 1024)}MB`);
    console.log(`  - Heap Total: ${Math.round(memUsage.heapTotal / 1024 / 1024)}MB`);
    console.log(`CPU 使用时间:`);
    console.log(`  - User: ${cpuUsage.user / 1000}ms`);
    console.log(`  - System: ${cpuUsage.system / 1000}ms`);
    
  }, 5000);
}

// 启动监控
// monitorProcess();

child_process 模块

child_process 模块提供了创建子进程的能力,允许 Node.js 应用程序执行外部命令、运行其他脚本或启动其他应用程序。这对于系统集成、任务执行和并行处理非常重要。

常用方法

异步方法
  • exec(command, [options], callback) - 执行命令,缓冲输出
  • execFile(file, [args], [options], callback) - 执行文件,缓冲输出
  • spawn(command, [args], [options]) - 启动进程,流式输出
  • fork(module, [args], [options]) - 创建 Node.js 子进程
同步方法
  • execSync(command, [options]) - 同步执行命令
  • execFileSync(file, [args], [options]) - 同步执行文件
  • spawnSync(command, [args], [options]) - 同步启动进程
事件
  • 'close' - 子进程关闭时触发
  • 'exit' - 子进程退出时触发
  • 'error' - 发生错误时触发
  • 'message' - 接收到消息时触发(仅 fork)

示例

使用 exec 执行外部命令

基本 exec 使用:

javascript 复制代码
const { exec } = require('child_process');

// 基本命令执行
exec('ls -la', (error, stdout, stderr) => {
  if (error) {
    console.error(`执行出错: ${error}`);
    return;
  }
  
  if (stderr) {
    console.error(`stderr: ${stderr}`);
    return;
  }
  
  console.log(`stdout:\n${stdout}`);
});

// 带选项的命令执行
exec('pwd', { 
  cwd: '/tmp',           // 设置工作目录
  env: process.env,      // 环境变量
  timeout: 5000,         // 超时时间
  maxBuffer: 1024 * 1024 // 最大缓冲区
}, (error, stdout, stderr) => {
  if (error) {
    console.error(`错误: ${error.message}`);
    return;
  }
  console.log(`当前目录: ${stdout.trim()}`);
});

// Promise 封装的 exec
const { promisify } = require('util');
const execPromise = promisify(exec);

async function execAsync(command) {
  try {
    const { stdout, stderr } = await execPromise(command);
    if (stderr) {
      console.warn(`警告: ${stderr}`);
    }
    return stdout.trim();
  } catch (error) {
    throw new Error(`命令执行失败: ${error.message}`);
  }
}

// 使用 Promise 版本
async function getSystemInfo() {
  try {
    const nodeVersion = await execAsync('node --version');
    const npmVersion = await execAsync('npm --version');
    const gitVersion = await execAsync('git --version');
    
    console.log('系统信息:');
    console.log(`Node.js: ${nodeVersion}`);
    console.log(`npm: ${npmVersion}`);
    console.log(`Git: ${gitVersion}`);
  } catch (error) {
    console.error('获取系统信息失败:', error.message);
  }
}

getSystemInfo();

高级命令执行器:

javascript 复制代码
const { exec } = require('child_process');
const { promisify } = require('util');

class CommandExecutor {
  constructor(options = {}) {
    this.defaultTimeout = options.timeout || 30000;
    this.defaultCwd = options.cwd || process.cwd();
    this.defaultEnv = { ...process.env, ...options.env };
    this.execAsync = promisify(exec);
  }

  async run(command, options = {}) {
    const execOptions = {
      cwd: options.cwd || this.defaultCwd,
      env: options.env || this.defaultEnv,
      timeout: options.timeout || this.defaultTimeout,
      maxBuffer: options.maxBuffer || 1024 * 1024 * 10 // 10MB
    };

    const startTime = Date.now();
    
    try {
      console.log(`🔄 执行命令: ${command}`);
      const { stdout, stderr } = await this.execAsync(command, execOptions);
      
      const duration = Date.now() - startTime;
      
      if (stderr && !options.ignoreStderr) {
        console.warn(`⚠️  stderr: ${stderr.trim()}`);
      }
      
      console.log(`✅ 命令完成 (${duration}ms)`);
      return {
        success: true,
        stdout: stdout.trim(),
        stderr: stderr.trim(),
        duration
      };
      
    } catch (error) {
      const duration = Date.now() - startTime;
      console.error(`❌ 命令失败 (${duration}ms): ${error.message}`);
      
      return {
        success: false,
        error: error.message,
        stdout: error.stdout || '',
        stderr: error.stderr || '',
        duration
      };
    }
  }

  async runSequential(commands, options = {}) {
    const results = [];
    
    for (const command of commands) {
      const result = await this.run(command, options);
      results.push({ command, ...result });
      
      if (!result.success && options.stopOnError !== false) {
        console.error(`命令序列在 "${command}" 处失败,停止执行`);
        break;
      }
    }
    
    return results;
  }

  async runParallel(commands, options = {}) {
    const promises = commands.map(command => 
      this.run(command, options).then(result => ({ command, ...result }))
    );
    
    return Promise.all(promises);
  }

  async exists(command) {
    const testCommand = process.platform === 'win32' 
      ? `where ${command}`
      : `which ${command}`;
    
    const result = await this.run(testCommand, { ignoreStderr: true });
    return result.success;
  }
}

// 使用示例
async function demonstrateCommandExecution() {
  const executor = new CommandExecutor({
    timeout: 10000,
    cwd: process.cwd()
  });

  // 检查命令是否存在
  const hasGit = await executor.exists('git');
  const hasDocker = await executor.exists('docker');
  
  console.log('命令可用性检查:');
  console.log(`Git: ${hasGit ? '✅' : '❌'}`);
  console.log(`Docker: ${hasDocker ? '✅' : '❌'}`);

  // 顺序执行命令
  if (hasGit) {
    const gitCommands = [
      'git status --porcelain',
      'git branch --show-current',
      'git log -1 --oneline'
    ];
    
    console.log('\n顺序执行 Git 命令:');
    const gitResults = await executor.runSequential(gitCommands, {
      ignoreStderr: true
    });
    
    gitResults.forEach(result => {
      if (result.success) {
        console.log(`${result.command}: ${result.stdout || '(无输出)'}`);
      }
    });
  }

  // 并行执行系统信息命令
  const systemCommands = [
    'node --version',
    'npm --version',
    'echo $HOME'
  ];
  
  console.log('\n并行执行系统命令:');
  const systemResults = await executor.runParallel(systemCommands);
  
  systemResults.forEach(result => {
    if (result.success) {
      console.log(`${result.command}: ${result.stdout}`);
    }
  });
}

demonstrateCommandExecution();
使用 spawn 启动进程

基本 spawn 使用:

javascript 复制代码
const { spawn } = require('child_process');

// 基本 spawn 使用
const ls = spawn('ls', ['-la', '/usr']);

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

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

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

ls.on('error', (err) => {
  console.error('子进程出错:', err);
});

// 交互式进程示例
function createInteractiveProcess(command, args = []) {
  const child = spawn(command, args, {
    stdio: ['pipe', 'pipe', 'pipe'], // stdin, stdout, stderr
    shell: false
  });

  // 处理输出
  child.stdout.on('data', (data) => {
    process.stdout.write(`[${command}] ${data}`);
  });

  child.stderr.on('data', (data) => {
    process.stderr.write(`[${command} ERROR] ${data}`);
  });

  // 处理进程事件
  child.on('close', (code, signal) => {
    console.log(`\n[${command}] 进程关闭: 退出码=${code}, 信号=${signal}`);
  });

  child.on('error', (error) => {
    console.error(`[${command}] 进程错误:`, error.message);
  });

  return child;
}

// 使用示例
const pythonProcess = createInteractiveProcess('python3', ['-i']);

// 向子进程发送输入
setTimeout(() => {
  pythonProcess.stdin.write('print("Hello from Node.js!")\n');
}, 1000);

setTimeout(() => {
  pythonProcess.stdin.write('2 + 2\n');
}, 2000);

setTimeout(() => {
  pythonProcess.stdin.write('exit()\n');
}, 3000);

进程管理器:

javascript 复制代码
const { spawn, fork } = require('child_process');
const path = require('path');

class ProcessManager {
  constructor() {
    this.processes = new Map();
    this.processCounter = 0;
  }

  spawn(command, args = [], options = {}) {
    const processId = `proc_${++this.processCounter}`;
    const defaultOptions = {
      stdio: ['pipe', 'pipe', 'pipe'],
      env: process.env,
      ...options
    };

    const child = spawn(command, args, defaultOptions);
    
    const processInfo = {
      id: processId,
      command,
      args,
      child,
      startTime: Date.now(),
      status: 'running'
    };

    this.processes.set(processId, processInfo);

    // 设置事件监听
    child.on('close', (code, signal) => {
      processInfo.status = 'closed';
      processInfo.exitCode = code;
      processInfo.signal = signal;
      processInfo.endTime = Date.now();
      processInfo.duration = processInfo.endTime - processInfo.startTime;
      
      console.log(`进程 ${processId} 关闭: 退出码=${code}, 耗时=${processInfo.duration}ms`);
    });

    child.on('error', (error) => {
      processInfo.status = 'error';
      processInfo.error = error;
      console.error(`进程 ${processId} 错误:`, error.message);
    });

    console.log(`启动进程 ${processId}: ${command} ${args.join(' ')}`);
    return processInfo;
  }

  // 创建 Node.js 子进程
  forkNode(scriptPath, args = [], options = {}) {
    const processId = `fork_${++this.processCounter}`;
    
    const child = fork(scriptPath, args, {
      silent: true, // 不继承父进程的 stdio
      ...options
    });

    const processInfo = {
      id: processId,
      type: 'fork',
      scriptPath,
      args,
      child,
      startTime: Date.now(),
      status: 'running'
    };

    this.processes.set(processId, processInfo);

    // IPC 消息处理
    child.on('message', (message) => {
      console.log(`[${processId}] 收到消息:`, message);
    });

    child.on('close', (code, signal) => {
      processInfo.status = 'closed';
      processInfo.exitCode = code;
      processInfo.endTime = Date.now();
      processInfo.duration = processInfo.endTime - processInfo.startTime;
    });

    child.on('error', (error) => {
      processInfo.status = 'error';
      processInfo.error = error;
    });

    console.log(`Fork 进程 ${processId}: ${scriptPath}`);
    return processInfo;
  }

  // 终止进程
  kill(processId, signal = 'SIGTERM') {
    const processInfo = this.processes.get(processId);
    if (!processInfo) {
      throw new Error(`进程 ${processId} 不存在`);
    }

    if (processInfo.status !== 'running') {
      console.log(`进程 ${processId} 已经结束`);
      return;
    }

    console.log(`终止进程 ${processId} (信号: ${signal})`);
    processInfo.child.kill(signal);
  }

  // 向进程发送消息(仅 fork 的 Node.js 进程)
  sendMessage(processId, message) {
    const processInfo = this.processes.get(processId);
    if (!processInfo || processInfo.type !== 'fork') {
      throw new Error(`进程 ${processId} 不是 fork 进程或不存在`);
    }

    processInfo.child.send(message);
  }

  // 获取所有进程状态
  getProcesses() {
    const result = {};
    for (const [id, info] of this.processes) {
      result[id] = {
        id: info.id,
        command: info.command || info.scriptPath,
        status: info.status,
        pid: info.child.pid,
        startTime: info.startTime,
        duration: info.endTime ? info.duration : Date.now() - info.startTime,
        exitCode: info.exitCode
      };
    }
    return result;
  }

  // 等待所有进程结束
  async waitAll() {
    const promises = [];
    
    for (const processInfo of this.processes.values()) {
      if (processInfo.status === 'running') {
        promises.push(new Promise((resolve) => {
          processInfo.child.on('close', resolve);
        }));
      }
    }
    
    await Promise.all(promises);
  }

  // 清理已结束的进程
  cleanup() {
    for (const [id, processInfo] of this.processes) {
      if (processInfo.status !== 'running') {
        this.processes.delete(id);
      }
    }
  }
}

// 使用示例
async function demonstrateProcessManager() {
  const pm = new ProcessManager();

  // 启动一些进程
  const proc1 = pm.spawn('echo', ['Hello World']);
  const proc2 = pm.spawn('sleep', ['2']);
  const proc3 = pm.spawn('ls', ['-la']);

  // 等待一段时间
  await new Promise(resolve => setTimeout(resolve, 1000));

  // 查看进程状态
  console.log('\n当前进程状态:');
  console.table(pm.getProcesses());

  // 等待所有进程结束
  await pm.waitAll();

  console.log('\n所有进程已结束');
  console.table(pm.getProcesses());

  // 清理
  pm.cleanup();
}

demonstrateProcessManager();

工作进程池示例:

javascript 复制代码
const { fork } = require('child_process');
const path = require('path');

// worker.js 内容
const workerScript = `
process.on('message', ({ taskId, data }) => {
  // 模拟计算密集型任务
  const start = Date.now();
  let result = 0;
  
  for (let i = 0; i < data.iterations; i++) {
    result += Math.random();
  }
  
  const duration = Date.now() - start;
  
  process.send({
    taskId,
    result,
    duration,
    workerId: process.pid
  });
});

console.log('Worker ready, PID:', process.pid);
`;

// 创建 worker 文件
const fs = require('fs');
const workerPath = path.join(__dirname, 'worker.js');
fs.writeFileSync(workerPath, workerScript);

class WorkerPool {
  constructor(poolSize = require('os').cpus().length) {
    this.poolSize = poolSize;
    this.workers = [];
    this.taskQueue = [];
    this.taskIdCounter = 0;
    this.pendingTasks = new Map();
    
    this.initWorkers();
  }

  initWorkers() {
    for (let i = 0; i < this.poolSize; i++) {
      const worker = fork(workerPath);
      
      worker.on('message', (result) => {
        this.handleWorkerResult(worker, result);
      });
      
      worker.on('error', (error) => {
        console.error(`Worker ${worker.pid} 错误:`, error);
      });
      
      worker.on('exit', (code) => {
        console.log(`Worker ${worker.pid} 退出,代码: ${code}`);
        this.replaceWorker(worker);
      });
      
      this.workers.push({
        process: worker,
        busy: false,
        taskCount: 0
      });
    }
    
    console.log(`工作进程池初始化完成,${this.poolSize} 个 worker`);
  }

  handleWorkerResult(workerProcess, result) {
    // 找到对应的 worker
    const worker = this.workers.find(w => w.process.pid === workerProcess.pid);
    if (worker) {
      worker.busy = false;
      worker.taskCount++;
    }

    // 处理任务结果
    const { taskId } = result;
    const taskInfo = this.pendingTasks.get(taskId);
    
    if (taskInfo) {
      taskInfo.resolve(result);
      this.pendingTasks.delete(taskId);
    }

    // 处理队列中的下一个任务
    this.processQueue();
  }

  replaceWorker(deadWorker) {
    const index = this.workers.findIndex(w => w.process === deadWorker);
    if (index !== -1) {
      const newWorker = fork(workerPath);
      
      newWorker.on('message', (result) => {
        this.handleWorkerResult(newWorker, result);
      });
      
      this.workers[index] = {
        process: newWorker,
        busy: false,
        taskCount: 0
      };
    }
  }

  async executeTask(data) {
    return new Promise((resolve, reject) => {
      const taskId = ++this.taskIdCounter;
      const taskInfo = {
        taskId,
        data,
        resolve,
        reject,
        timestamp: Date.now()
      };

      this.taskQueue.push(taskInfo);
      this.pendingTasks.set(taskId, taskInfo);
      
      this.processQueue();
    });
  }

  processQueue() {
    if (this.taskQueue.length === 0) return;

    // 找到空闲的 worker
    const availableWorker = this.workers.find(w => !w.busy);
    if (!availableWorker) return;

    const task = this.taskQueue.shift();
    availableWorker.busy = true;
    
    // 发送任务给 worker
    availableWorker.process.send({
      taskId: task.taskId,
      data: task.data
    });
  }

  getStats() {
    return {
      totalWorkers: this.workers.length,
      busyWorkers: this.workers.filter(w => w.busy).length,
      queueLength: this.taskQueue.length,
      pendingTasks: this.pendingTasks.size,
      workerStats: this.workers.map(w => ({
        pid: w.process.pid,
        busy: w.busy,
        taskCount: w.taskCount
      }))
    };
  }

  async shutdown() {
    console.log('关闭工作进程池...');
    
    // 等待所有任务完成
    while (this.pendingTasks.size > 0) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
    
    // 终止所有 worker
    for (const worker of this.workers) {
      worker.process.kill();
    }
    
    console.log('工作进程池已关闭');
  }
}

// 使用示例
async function demonstrateWorkerPool() {
  const pool = new WorkerPool(4);
  
  // 等待 worker 初始化
  await new Promise(resolve => setTimeout(resolve, 500));
  
  console.log('提交任务到工作池...');
  const tasks = [];
  
  // 提交多个计算任务
  for (let i = 0; i < 10; i++) {
    const task = pool.executeTask({
      iterations: 1000000 + Math.floor(Math.random() * 1000000)
    });
    tasks.push(task);
  }
  
  // 监控进度
  const progressInterval = setInterval(() => {
    const stats = pool.getStats();
    console.log(`进度: 忙碌 worker: ${stats.busyWorkers}/${stats.totalWorkers}, 队列: ${stats.queueLength}, 等待结果: ${stats.pendingTasks}`);
  }, 500);
  
  // 等待所有任务完成
  const results = await Promise.all(tasks);
  clearInterval(progressInterval);
  
  console.log('\n所有任务完成!');
  console.log('结果摘要:');
  results.forEach((result, index) => {
    console.log(`任务 ${index}: 结果=${result.result.toFixed(2)}, 耗时=${result.duration}ms, Worker PID=${result.workerId}`);
  });
  
  console.log('\n最终统计:');
  console.table(pool.getStats().workerStats);
  
  await pool.shutdown();
  
  // 清理临时文件
  fs.unlinkSync(workerPath);
}

demonstrateWorkerPool();

util.promisify

util.promisify 是 Node.js 8.0+ 提供的工具函数,用于将传统的基于回调的异步函数转换为返回 Promise 的函数。这使得可以使用 async/await 语法来处理异步操作,提高代码的可读性和可维护性。

常用场景

适用的函数模式

util.promisify 适用于遵循 Node.js 回调约定的函数:

  • 回调函数是最后一个参数
  • 回调函数的第一个参数是错误对象 (err)
  • 如果没有错误,err 为 null 或 undefined
  • 后续参数是成功的返回值
常见用例
  • 文件系统操作 (fs.readFile, fs.writeFile 等)
  • 网络操作 (dns.lookup 等)
  • 第三方库的回调式 API
  • 自定义的回调式函数

示例

使用 util.promisify 将 fs.readFile 转换为 Promise 版本

基本用法:

javascript 复制代码
const util = require('util');
const fs = require('fs');

// 传统回调方式
fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('读取失败:', err);
    return;
  }
  console.log('文件内容:', data);
});

// 使用 util.promisify 转换
const readFileAsync = util.promisify(fs.readFile);

async function readFileExample() {
  try {
    const data = await readFileAsync('example.txt', 'utf8');
    console.log('文件内容:', data);
  } catch (error) {
    console.error('读取失败:', error.message);
  }
}

readFileExample();

// 也可以直接使用 fs.promises (Node.js 10+)
const fsPromises = require('fs').promises;

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

批量转换文件系统函数:

javascript 复制代码
const util = require('util');
const fs = require('fs');

// 批量转换常用的 fs 函数
const fsAsync = {
  readFile: util.promisify(fs.readFile),
  writeFile: util.promisify(fs.writeFile),
  appendFile: util.promisify(fs.appendFile),
  readdir: util.promisify(fs.readdir),
  stat: util.promisify(fs.stat),
  mkdir: util.promisify(fs.mkdir),
  rmdir: util.promisify(fs.rmdir),
  unlink: util.promisify(fs.unlink),
  access: util.promisify(fs.access)
};

// 使用转换后的函数
async function fileOperations() {
  try {
    // 检查文件是否存在
    await fsAsync.access('data.txt');
    console.log('文件存在');
    
    // 读取文件状态
    const stats = await fsAsync.stat('data.txt');
    console.log('文件大小:', stats.size, '字节');
    console.log('最后修改时间:', stats.mtime);
    
    // 读取文件内容
    const content = await fsAsync.readFile('data.txt', 'utf8');
    console.log('文件内容长度:', content.length);
    
    // 写入新内容
    const newContent = content + '\n添加的新行';
    await fsAsync.writeFile('data_copy.txt', newContent);
    console.log('文件复制完成');
    
  } catch (error) {
    if (error.code === 'ENOENT') {
      console.log('文件不存在');
    } else {
      console.error('操作失败:', error.message);
    }
  }
}

fileOperations();

转换第三方库的回调函数:

javascript 复制代码
const util = require('util');

// 模拟一个第三方库的回调式 API
function fetchData(url, callback) {
  // 模拟异步请求
  setTimeout(() => {
    if (url.includes('error')) {
      callback(new Error('请求失败'));
    } else {
      callback(null, { url, data: '模拟数据', timestamp: Date.now() });
    }
  }, Math.random() * 1000);
}

function processData(data, callback) {
  setTimeout(() => {
    try {
      const processed = {
        ...data,
        processed: true,
        processTime: Date.now()
      };
      callback(null, processed);
    } catch (error) {
      callback(error);
    }
  }, 200);
}

// 转换为 Promise 版本
const fetchDataAsync = util.promisify(fetchData);
const processDataAsync = util.promisify(processData);

// 使用转换后的函数
async function dataWorkflow() {
  try {
    console.log('开始数据处理流程...');
    
    // 并行获取多个数据源
    const urls = [
      'https://api.example.com/users',
      'https://api.example.com/posts',
      'https://api.example.com/comments'
    ];
    
    const fetchPromises = urls.map(url => fetchDataAsync(url));
    const results = await Promise.all(fetchPromises);
    
    console.log(`成功获取 ${results.length} 个数据源`);
    
    // 串行处理数据
    const processedResults = [];
    for (const result of results) {
      const processed = await processDataAsync(result);
      processedResults.push(processed);
    }
    
    console.log('所有数据处理完成:', processedResults.length);
    return processedResults;
    
  } catch (error) {
    console.error('数据处理失败:', error.message);
    throw error;
  }
}

dataWorkflow();

创建自定义的 promisify 工具:

javascript 复制代码
const util = require('util');

// 高级 promisify 工具类
class PromisifyUtils {
  // 转换单个函数
  static promisify(fn, thisArg = null) {
    return util.promisify(fn.bind(thisArg));
  }
  
  // 批量转换对象的方法
  static promisifyAll(obj, suffix = 'Async') {
    const promisified = {};
    
    for (const [key, value] of Object.entries(obj)) {
      if (typeof value === 'function') {
        promisified[key + suffix] = util.promisify(value.bind(obj));
      }
    }
    
    return promisified;
  }
  
  // 转换类的所有方法
  static promisifyMethods(instance, methods, suffix = 'Async') {
    const promisified = {};
    
    for (const method of methods) {
      if (typeof instance[method] === 'function') {
        promisified[method + suffix] = util.promisify(instance[method].bind(instance));
      }
    }
    
    return promisified;
  }
  
  // 支持自定义符号的 promisify
  static customPromisify(fn, customSymbol) {
    if (fn[customSymbol]) {
      return fn[customSymbol];
    }
    return util.promisify(fn);
  }
}

// 示例:数据库操作类
class Database {
  connect(callback) {
    setTimeout(() => {
      this.connected = true;
      callback(null, 'Connected to database');
    }, 100);
  }
  
  query(sql, callback) {
    setTimeout(() => {
      if (!this.connected) {
        return callback(new Error('Database not connected'));
      }
      
      // 模拟查询结果
      const result = {
        rows: [
          { id: 1, name: 'Alice' },
          { id: 2, name: 'Bob' }
        ],
        rowCount: 2
      };
      
      callback(null, result);
    }, 200);
  }
  
  close(callback) {
    setTimeout(() => {
      this.connected = false;
      callback(null, 'Database closed');
    }, 50);
  }
}

// 使用工具类转换数据库操作
async function databaseExample() {
  const db = new Database();
  
  // 方法1:逐个转换
  const connectAsync = util.promisify(db.connect.bind(db));
  const queryAsync = util.promisify(db.query.bind(db));
  const closeAsync = util.promisify(db.close.bind(db));
  
  // 方法2:批量转换
  const dbAsync = PromisifyUtils.promisifyMethods(
    db, 
    ['connect', 'query', 'close']
  );
  
  try {
    // 连接数据库
    await dbAsync.connectAsync();
    console.log('数据库连接成功');
    
    // 执行查询
    const result = await dbAsync.queryAsync('SELECT * FROM users');
    console.log('查询结果:', result.rows);
    
    // 关闭连接
    await dbAsync.closeAsync();
    console.log('数据库连接已关闭');
    
  } catch (error) {
    console.error('数据库操作失败:', error.message);
  }
}

databaseExample();

处理特殊情况和错误:

javascript 复制代码
const util = require('util');

// 处理多返回值的回调函数
function multiValueCallback(input, callback) {
  setTimeout(() => {
    const result1 = input * 2;
    const result2 = input * 3;
    const result3 = input * 4;
    
    callback(null, result1, result2, result3);
  }, 100);
}

// util.promisify 只返回第一个值
const multiValueAsync = util.promisify(multiValueCallback);

async function handleMultiValue() {
  try {
    const result = await multiValueAsync(5);
    console.log('第一个结果:', result); // 只有第一个值: 10
    
    // 如果需要所有值,需要自定义包装
    const multiValueCustom = (input) => {
      return new Promise((resolve, reject) => {
        multiValueCallback(input, (err, val1, val2, val3) => {
          if (err) {
            reject(err);
          } else {
            resolve([val1, val2, val3]); // 返回数组
          }
        });
      });
    };
    
    const allResults = await multiValueCustom(5);
    console.log('所有结果:', allResults); // [10, 15, 20]
    
  } catch (error) {
    console.error('错误:', error.message);
  }
}

handleMultiValue();

// 处理不符合 Node.js 约定的回调函数
function nonStandardCallback(input, callback) {
  // 这个函数不遵循 Node.js 回调约定
  // 成功时:callback(result)
  // 失败时:callback(null, error) 
  setTimeout(() => {
    if (input < 0) {
      callback(null, new Error('输入不能为负数'));
    } else {
      callback(input * 2);
    }
  }, 100);
}

// 需要自定义包装器
function createCustomPromise(fn) {
  return function promisified(...args) {
    return new Promise((resolve, reject) => {
      fn(...args, (result, error) => {
        if (error) {
          reject(error);
        } else {
          resolve(result);
        }
      });
    });
  };
}

const nonStandardAsync = createCustomPromise(nonStandardCallback);

async function handleNonStandard() {
  try {
    const result = await nonStandardAsync(10);
    console.log('结果:', result); // 20
    
    await nonStandardAsync(-5); // 这会抛出错误
  } catch (error) {
    console.error('捕获的错误:', error.message);
  }
}

handleNonStandard();

进程间通信处理流程:

flowchart TD A[传统回调函数] --> B[util.promisify转换] B --> C{是否符合Node.js约定?} C -->|是| D[直接转换成功] C -->|否| E[需要自定义包装器] D --> F[使用async/await] E --> G[创建Promise包装器] G --> F F --> H{函数执行} H -->|成功| I[返回结果] H -->|失败| J[抛出异常] I --> K[Promise resolved] J --> L[Promise rejected] K --> M[继续执行] L --> N[错误处理]

总结

Node.js 核心模块总结

Node.js 的核心模块为服务端 JavaScript 开发提供了强大的基础设施:

主要模块功能对比
模块 主要功能 使用场景 关键特性
fs 文件系统操作 文件读写、目录管理 同步/异步/Promise 三种模式
path 路径处理 跨平台路径操作 自动处理分隔符差异
os 系统信息 系统监控、环境检测 获取硬件和系统状态
process 进程控制 环境变量、命令行参数 全局对象,进程生命周期管理
child_process 子进程管理 执行外部命令、并行处理 exec/spawn/fork 多种创建方式
util.promisify Promise 转换 回调函数现代化 将回调式 API 转换为 Promise
最佳实践建议
  1. 异步优先: 优先使用异步 API,避免阻塞事件循环
  2. 错误处理: 始终处理错误,使用 try-catch 包装 async/await
  3. 资源清理: 及时关闭文件句柄、终止子进程
  4. 跨平台兼容: 使用 path 模块处理路径,考虑操作系统差异
  5. 性能监控: 利用 os 和 process 模块监控系统资源使用情况
现代化开发趋势
  • Promise/async-await: 替代传统回调,提高代码可读性
  • ES Modules: 逐步迁移到 ESM 模块系统
  • TypeScript: 增强类型安全和开发体验
  • 性能优化: 合理使用子进程和工作线程处理 CPU 密集型任务
相关推荐
研☆香2 小时前
html页面如何精准布局
前端·html
零下32摄氏度2 小时前
【前端干货】接口在 Postman 测试很快,页面加载咋就慢?
前端·程序人生·postman
全栈陈序员3 小时前
说说你对 Vue 的理解
前端·javascript·vue.js·学习·前端框架
全栈技术负责人3 小时前
Ling框架:针对AIGC工作流中JSON数据流式处理的解决方案
前端·ai
自由与自然3 小时前
实现类似van-dialog自定义弹框
前端·javascript·html
KLW753 小时前
vue3中操作样式的变化
前端·javascript·vue.js
天天讯通3 小时前
BI 报表:呼叫中心的伪刚需
大数据·前端·数据库
自由与自然3 小时前
栅格布局常用用法
开发语言·前端·javascript
Violet_YSWY3 小时前
讲一下ruoyi-vue3的前端项目目录结构
前端·javascript·vue.js