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();
文件操作流程图:
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- 当前进程的 PIDprocess.ppid- 父进程的 PIDprocess.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();
进程间通信处理流程:
总结
Node.js 核心模块总结
Node.js 的核心模块为服务端 JavaScript 开发提供了强大的基础设施:
主要模块功能对比
| 模块 | 主要功能 | 使用场景 | 关键特性 |
|---|---|---|---|
| fs | 文件系统操作 | 文件读写、目录管理 | 同步/异步/Promise 三种模式 |
| path | 路径处理 | 跨平台路径操作 | 自动处理分隔符差异 |
| os | 系统信息 | 系统监控、环境检测 | 获取硬件和系统状态 |
| process | 进程控制 | 环境变量、命令行参数 | 全局对象,进程生命周期管理 |
| child_process | 子进程管理 | 执行外部命令、并行处理 | exec/spawn/fork 多种创建方式 |
| util.promisify | Promise 转换 | 回调函数现代化 | 将回调式 API 转换为 Promise |
最佳实践建议
- 异步优先: 优先使用异步 API,避免阻塞事件循环
- 错误处理: 始终处理错误,使用 try-catch 包装 async/await
- 资源清理: 及时关闭文件句柄、终止子进程
- 跨平台兼容: 使用 path 模块处理路径,考虑操作系统差异
- 性能监控: 利用 os 和 process 模块监控系统资源使用情况
现代化开发趋势
- Promise/async-await: 替代传统回调,提高代码可读性
- ES Modules: 逐步迁移到 ESM 模块系统
- TypeScript: 增强类型安全和开发体验
- 性能优化: 合理使用子进程和工作线程处理 CPU 密集型任务