Node.js中GET请求JSON数据无法存入全局变量及写入文件问题
解决异步GET请求数据无法存入全局变量并写入文件的问题
你碰到的核心问题是JavaScript的异步执行机制——http.get是异步操作,它不会阻塞后续代码运行。你写在两个请求之后的console.log(g_last)和fs.writeFile会在两个请求的end回调触发前就执行,这时候tmp_json还没被赋值,g_last还是初始的0,自然写入的文件是空的。
解决方案:用Promise + async/await管控异步流程
我们可以把每个异步GET请求包装成Promise,再用Promise.all等待所有请求完成后,统一处理数据并写入文件,这样就能保证数据都准备好后再执行写入操作。
步骤1:封装异步GET请求为Promise
先写一个复用的函数,把http.get转换成返回Promise的形式,方便后续用async/await处理:
const fs = require("fs"); const http = require("http"); // 封装异步GET请求为Promise function httpGet(url) { return new Promise((resolve, reject) => { http.get(url, (resp) => { let data = ''; resp.on('data', (chunk) => { data += chunk; }); resp.on('end', () => { try { // 解析JSON数据并返回 const parsedData = JSON.parse(data); resolve(parsedData); } catch (parseErr) { reject(new Error(`解析JSON失败: ${parseErr.message}`)); } }); }).on("error", (reqErr) => { reject(new Error(`请求失败: ${reqErr.message}`)); }); }); }
步骤2:用async/await并行处理请求并写入文件
通过async/await和Promise.all,我们可以并行发起两个请求,等待所有请求完成后再处理数据和写入文件:
// 主逻辑函数 async function fetchAndSaveData() { const tmp_json = {}; let g_last = 0; try { // 并行发起两个请求,等待所有请求完成 const [server1Data, server2Data] = await Promise.all([ httpGet('server:api'), httpGet('server2:api') ]); // 将请求结果存入tmp_json tmp_json.server1 = server1Data; tmp_json.server2 = server2Data; // 更新变量g_last(这里取第二个请求的height为例) g_last = server2Data.height; console.log(g_last); // 输出256 // 将数据写入文件 const jsonStr = JSON.stringify(tmp_json); fs.writeFile('data.json', jsonStr, 'utf8', (writeErr) => { if (writeErr) { console.log(`写入文件失败: ${writeErr.message}`); } else { console.log("数据已成功写入data.json"); } }); } catch (err) { // 捕获请求或解析过程中的错误 console.log(err.message); } } // 执行主函数 fetchAndSaveData();
如果你想用fs.createWriteStream写入
如果偏好使用流的方式写入,只需要把上面的fs.writeFile部分替换成以下代码即可,同样要确保在所有请求完成后再写入:
const writeStream = fs.createWriteStream('data.json', 'utf8'); writeStream.write(JSON.stringify(tmp_json)); writeStream.end(); writeStream.on('finish', () => { console.log("数据已通过流成功写入文件"); }); writeStream.on('error', (streamErr) => { console.log(`写入流出错: ${streamErr.message}`); });
关键注意点
- 错误处理:一定要捕获请求、JSON解析和文件写入过程中的错误,避免某个环节出错导致整个流程无响应
- 请求顺序:如果两个请求有依赖关系(比如需要先获取server1的数据再请求server2),把
Promise.all改成顺序执行的await即可,比如先const server1Data = await httpGet('server:api'),再const server2Data = await httpGet('server2:api') - 避免全局变量滥用:尽量把数据放在函数内部(比如示例中的
tmp_json),减少全局变量的使用,避免异步操作导致的变量污染问题
内容的提问来源于stack exchange,提问作者MAx Shvedov
相关产品推荐
相关产品推荐

