Node.js调用fs.appendFile后服务重启并重复发送请求问题求助
问题根因排查
- Promise状态未正确结算:你封装的
streamActivity返回的Promise,在请求成功分支只调用了存储函数,从未执行resolve(),导致Promise始终处于pending状态。如果上层逻辑有请求超时重试、批量请求等待完成的机制,就会判定请求失败触发重试,导致重复发送相同请求。 - 异步回调抛错导致进程崩溃:
appendToFile1的fs异步回调中直接throw err,异步回调内抛出的错误无法被外层捕获,会直接触发Node.js未捕获异常事件,导致进程退出。如果你的服务配置了进程守护(比如pm2、systemd自动重启),进程崩溃后会自动重启,重启后重新执行任务逻辑,就会出现不断重启+重复发请求的死循环。 - 并发写入隐患:当前
appendToFile1是异步无等待调用,高并发请求场景下会出现多个写入操作同时执行,导致文件内容错乱、写入失败的问题,进一步触发上述抛错崩溃的问题。 - 非法JSON格式问题:直接拼接JSON字符串写入文件,最终生成的不是合法的JSON结构,后续读取解析时会报错,也是潜在的崩溃诱因。
修复方案
首先改造appendToFile1为Promise风格,统一错误处理,避免直接抛错,同时增加换行符用JSON Lines格式存储,避免内容错乱:
function appendToFile1(file, payload) { return new Promise((resolve, reject) => { // 新增换行符,每行存储一个JSON对象,后续读取更方便 const content = JSON.stringify({payload}) + '\n' fs.appendFile(file, content, (err) => { if (err) return reject(err) console.log('Done writing') resolve() }) }) }
然后修改streamActivity的回调逻辑,等待写入完成后再正确结算Promise:
const streamActivity = (client) => (activityId) => { return new Promise((resolve, reject) => { client.streams.activity( { id: activityId, types: "time,heartrate,velocity_smooth,altitude,distance,latlng,cadence,watts,temp,moving,grade_smooth,average_speed", resolution: "high", }, async function (err, payload,next) { if (!err ) { try { // 等待写入完成再返回成功状态 await appendToFile1('activity-streams.json', payload) resolve(payload) } catch (writeErr) { // 写入错误统一抛给上层做重试/降级处理 reject(writeErr) } } else { reject(err) } } ); }); };
如果需要生成标准JSON数组存储,可以在首次写入前先写入[,后续每次写入前先加一个逗号(注意首条数据不要加逗号),所有数据写完后写入]即可。如果是持续写入的场景,更推荐使用上述JSON Lines格式,不需要处理数组边界,读写都更简便。
内容的提问来源于stack exchange,提问作者justLearning
相关产品推荐
相关产品推荐

