Node.js服务器中能否一次性存储API数据到变量并按需展示?
你的需求完全可以实现,先修正代码问题再优化
首先你的代码存在几个关键问题,导致无法正常获取并返回数据:
- 定义了异步函数但没有调用,
fetch请求根本没执行 - 就算调用了异步函数,
res.end()会在fetch完成前执行,因为异步操作不会阻塞主线程 - 直接把数组传给
res.end()会被转成逗号分隔的字符串,不是合法的响应格式
先修正基础问题,实现单次请求获取数据
把回调改成异步函数,等待fetch完成后再返回响应:
const http = require('http'); const url = require('url') http.createServer(async function (req, res) { const { query, pathname } = url.parse(req.url, true) let answer = []; try { // 直接await获取数据,避免嵌套then const response = await fetch('https://dummyjson.com/products'); const data = await response.json(); answer.push(data); } catch (err) { console.error('获取数据失败:', err); res.writeHead(500, { "Content-Type": 'application/json', "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "X-Requested-With" }); res.end(JSON.stringify({error: '获取数据失败'})); return; } res.writeHead(200, { "Content-Type": 'application/json', // 返回JSON格式更合理 "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "X-Requested-With" }); res.end(JSON.stringify(answer)); }).listen(8080); console.log('Server Started');
优化成「一次性获取,按需复用」的缓存版本
按照你的需求,我们可以把数据缓存到全局变量,首次请求时拉取API数据,之后所有请求直接复用缓存,还能根据需求返回不同数据:
const http = require('http'); const url = require('url'); // 全局缓存存储产品数据 let productCache = null; // 标记是否正在请求API,避免并发重复请求 let isFetching = false; http.createServer(async function (req, res) { const { query, pathname } = url.parse(req.url, true); // 处理跨域OPTIONS预检请求 if (req.method === 'OPTIONS') { res.writeHead(200, { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, OPTIONS", "Access-Control-Allow-Headers": "X-Requested-With" }); res.end(); return; } try { // 缓存为空且无请求时,拉取数据 if (!productCache && !isFetching) { isFetching = true; const response = await fetch('https://dummyjson.com/products'); const data = await response.json(); productCache = data.products; // 直接存储产品数组,方便后续按需处理 isFetching = false; } // 等待请求完成(如果正在拉取数据) while (isFetching) { await new Promise(resolve => setTimeout(resolve, 100)); } // 按需返回数据示例 let responseData = productCache; // 根据query参数返回单个产品 if (query.id) { responseData = productCache.find(item => item.id === parseInt(query.id)); } // 根据路径返回筛选后的产品 else if (pathname === '/top-rated') { responseData = productCache.filter(item => item.rating >= 4.5); } res.writeHead(200, { "Content-Type": 'application/json', "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "X-Requested-With" }); res.end(JSON.stringify(responseData)); } catch (err) { console.error('处理请求失败:', err); res.writeHead(500, { "Content-Type": 'application/json', "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "X-Requested-With" }); res.end(JSON.stringify({error: '服务器内部错误'})); isFetching = false; // 出错后重置请求标记 } }).listen(8080); console.log('Server Started on port 8080');
这个版本的优势:
- 仅首次请求会调用API,后续直接用缓存,减少不必要的网络请求
- 加入并发控制,避免多个请求同时触发API调用
- 可以根据请求参数或路径,灵活返回不同的数据(比如单个产品、筛选列表等)
内容的提问来源于stack exchange,提问作者Carlos Ospina
相关产品推荐
相关产品推荐

