如何在Node.js服务器中处理含长时任务与异步文件读取的并发请求
Node.js 非阻塞Web服务器实现方案
以下是满足需求的完整实现,同时优化了错误处理逻辑,确保服务器能并发处理请求且不阻塞主线程:
const fs = require('fs'); const http = require('http'); // 模拟长耗时任务(异步非阻塞) function longRunningTask(callback) { setTimeout(() => { callback(null, 'Long-running task completed'); }, 3000); // 模拟3秒的任务耗时 } // 异步读取文件(封装fs.readFile,统一错误处理) function readFileAsync(filePath, callback) { fs.readFile(filePath, 'utf8', (err, data) => { if (err) { return callback(err); } callback(null, data); }); } // 创建HTTP服务器 const server = http.createServer((req, res) => { // 设置响应头默认编码,避免乱码 res.setHeader('Content-Type', 'text/plain; charset=utf-8'); switch (req.url) { case '/': res.writeHead(200); res.end('Hello, world!\n'); break; case '/long-task': // 长任务通过异步回调执行,不阻塞主线程 longRunningTask((err, message) => { if (err) { res.writeHead(500); return res.end('Long task failed\n'); } res.writeHead(200); res.end(message + '\n'); }); break; case '/read-file': readFileAsync('example.txt', (err, data) => { if (err) { // 区分文件不存在和其他服务器错误 if (err.code === 'ENOENT') { res.writeHead(404); res.end('File not found\n'); } else { res.writeHead(500); res.end(`Error reading file: ${err.message}\n`); } return; } res.writeHead(200); res.end(data); }); break; default: res.writeHead(404); res.end('Not Found\n'); break; } }); // 启动服务器 server.listen(3000, () => { console.log('Server is listening on port 3000'); });
关键实现说明:
- 非阻塞并发处理:所有耗时操作(长任务、文件读取)都使用Node.js异步API(
setTimeout、fs.readFile),这些操作会被放入事件队列,主线程可以继续处理其他请求,不会被阻塞。 - 精准错误处理:
- 读取文件时,判断错误码
ENOENT返回404(文件不存在),其他错误返回500(服务器内部错误),提供更清晰的错误反馈。 - 长任务添加错误回调分支,避免未处理的异常导致服务器崩溃。
- 读取文件时,判断错误码
- 路由清晰化:使用
switch替代多if-else,路由逻辑更易维护。 - 响应编码设置:统一设置
Content-Type的编码为utf-8,避免中文内容乱码。
验证并发能力:
你可以同时发起多个请求测试:
- 访问
http://localhost:3000/long-task,然后立即访问http://localhost:3000/,根路由会立即返回响应,不会等待长任务完成。 - 同时发起多个
/long-task请求,服务器会并行处理所有任务,每个任务都会在3秒后返回结果。
内容的提问来源于stack exchange,提问作者Faizan Rasheed
相关产品推荐
相关产品推荐

