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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:20:40