You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中如何阻止服务器刷新事件重复记录日志?

解决Node.js事件与服务器结合时重复记录日志的问题

问题原因

每次HTTP请求到达服务器时,你都会在请求回调内调用eventemitter.on('log', ...)给log事件新增一个监听器。随着请求次数增加,监听器会不断累积,每次触发emit('log')时,所有已绑定的监听器都会执行,导致同一时间点的日志被重复记录。

解决方案

方案1:将事件监听器移到服务器逻辑外(推荐)

把监听器绑定代码放在http.createServer()外面,只执行一次绑定,这样无论多少请求,监听器始终只有一个,emit只会触发一次回调。

修改后的完整代码:

const {v4:uuid} = require('uuid');
const {format} = require('date-fns');
const EventEmitter = require('events');
const os = require('os');
const path = require('path');
const fs = require('fs');
const http = require('http');

const user = os.userInfo().username;
const eventemitter = new EventEmitter();

// 仅绑定一次log事件监听器
eventemitter.on('log', (date_time, res) => {
    const req_string = `Log event: '${uuid()}' emitted by ${user} at time:    ${date_time} hrs.\n`;

    // 用同步创建文件夹,避免异步创建时还未完成就写入日志
    if(!fs.existsSync(path.join(__dirname, 'server_folder'))){
        fs.mkdirSync(path.join(__dirname, 'server_folder'));
    }

    fs.appendFileSync(path.join(__dirname, 'server_folder', 'server_log.txt'), req_string, 'utf-8');
    res.write(req_string);
    res.end();
});

const server = http.createServer((req, res) => {
    const date_time = `${format(new Date, 'dd.MM.yyyy  HH:mm:ss')}`;
    // 触发事件时传递需要的参数
    eventemitter.emit('log', date_time, res);
});

server.listen(5000);

方案2:使用once替代on绑定监听器

如果必须在请求回调内绑定监听器,使用eventemitter.once()代替on(),这样监听器只会被触发一次,触发后会自动从事件中解绑,不会累积。

修改请求回调部分的代码:

const server = http.createServer((req, res)=>{
    const date_time = `${format(new Date, 'dd.MM.yyyy  HH:mm:ss')}`;
    // 使用once,监听器触发一次后自动解绑
    eventemitter.once('log', ()=>{
        const req_string = `Log event: '${uuid()}' emitted by ${user} at time:    ${date_time} hrs.\n`;
    
        if(!fs.existsSync(path.join(__dirname, 'server_folder'))){
            fs.mkdirSync(path.join(__dirname, 'server_folder'));
        }
    
        fs.appendFileSync(path.join(__dirname, 'server_folder', 'server_log.txt'), req_string, 'utf-8');
        res.write(req_string);
        res.end();
    })
    eventemitter.emit('log');
})

额外优化提示

原代码中fs.mkdir是异步方法,可能出现文件夹还未创建完成就执行appendFileSync的情况,改成同步的fs.mkdirSync可以避免这个潜在问题。

内容的提问来源于stack exchange,提问作者Abhrajit Saha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 22:03:27