ExpressJS与NodeJS页面刷新数组重复:需首次加载并单次输出
问题解决思路
核心问题分析
- 全局数组污染:
logtraceArr定义在路由处理函数外部,属于模块级变量,每次请求都会持续往数组里追加数据,导致后续请求返回重复内容。 - 异步操作未等待:文件读取、解析都是异步操作,但代码在触发这些操作后立刻调用
res.send(),此时异步任务还未完成,数组还没填充数据,所以首次请求返回空数组。
修复后的完整代码
var express = require("express"); var router = express.Router(); const fs = require("fs").promises; // 使用fs promise API简化异步处理 const path = require("path"); const readline = require('readline'); const directoryPath = path.resolve(__dirname,"../logtrace-filestore/edepoze-logs"); router.get("/", async function(req,res,next){ // 每次请求都创建新数组,避免全局污染 let logtraceArr = []; // 解析单条匹配内容 const fetchFileContentParsed = (fileContentObj) => { const logtraceObj = { Direction : '', FromServer: '', ToServer:'' }; const pipearray = fileContentObj.toString().split("|"); // 原循环无意义,直接取pipearray[5]即可 if (pipearray[5]) { const Direction = pipearray[5].split("::"); logtraceObj.Direction = Direction.length === 2 ? Direction[1] : ""; } logtraceArr.push(logtraceObj); }; // 读取单个文件并解析 const processSingleFile = async (file) => { const filePath = path.join(directoryPath, file); const readStream = fs.createReadStream(filePath); const rl = readline.createInterface({ input: readStream, crlfDelay: Infinity }); // 用Promise包裹readline的异步事件,确保文件处理完成后再返回 return new Promise((resolve) => { rl.on('line', (line) => { const regExp = /\[Event([^]+\])/g; const matchedContent = line.match(regExp); if (matchedContent) { fetchFileContentParsed(matchedContent); } }); rl.on('close', resolve); }); }; // 读取目录下所有文件并处理 const readFiles = async (dirname) => { const filenames = await fs.readdir(dirname); // 并行处理所有文件 await Promise.all(filenames.map(processSingleFile)); }; try { // 等待所有文件读取解析完成 await readFiles(directoryPath); res.header("Access-Control-Allow-Origin", "*"); res.contentType('application/json'); res.send(logtraceArr); } catch (err) { // 处理错误,返回500状态码 next(err); } }); module.exports = router;
关键修改点说明
- 移除全局数组:将
logtraceArr移到路由处理函数内部,每次请求都会创建新数组,避免重复追加数据。 - 异步操作Promise化:
- 使用
fs.promises替代回调式的fs.readdir,简化异步流程。 - 用Promise包裹
readline的事件监听,确保单个文件的所有行处理完成后再继续执行。
- 使用
- 等待异步任务完成:用
await等待readFiles完成所有文件的读取和解析,再发送响应,保证首次请求就能返回填充好的数据。 - 优化冗余代码:移除原代码中无意义的
for循环,直接处理pipearray[5]。
内容的提问来源于stack exchange,提问作者SaiPrasad_SP
相关产品推荐
相关产品推荐

