You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Node/Express/Axios应用中出现localhost未返回数据(ERR_EMPTY_RESPONSE)问题求助

Node/Express/Axios应用中出现localhost未返回数据(ERR_EMPTY_RESPONSE)问题求助

嘿,这个问题确实是异步处理逻辑+Express中间件的正确使用方式出了问题,我来帮你一步步搞定:

问题根源拆解

  1. 你的searchArt不是合格的Express中间件:它没有接收Express中间件必须的req, res, next三个参数,完全没法和Express的请求生命周期打通——既没法把API数据传递给后续路由,也没法告诉Express“我这个异步请求干完了,继续往下走”。
  2. 异步操作未被等待:Axios请求是异步的,但searchArt既没返回Promise,也没做任何等待处理,Express会直接跳过这个异步操作,执行后面的res.send(res.data)——但此时res.data根本不存在,而且异步请求还没完成,响应一直没发出去,最终导致浏览器超时报错。
  3. 路由里的res.send(res.data)是错误用法:Express的res对象本身没有data属性,你得把API拿到的数据存在请求/响应的上下文里(比如res.locals)才能在后续逻辑里用。

修改后的代码方案

第一步:修复models/metData.js,把searchArt改成标准中间件

这里我用async/await让异步逻辑更清晰,你也可以用.then/.catch的写法,效果一样:

'use strict';
import axios from "axios";

const metAPI = {
  // 改成Express中间件形式,接收req, res, next参数
  searchArt: async function(req, res, next) {
    try {
      // 等待Axios请求完成
      const response = await axios.get("https://collectionapi.metmuseum.org/public/collection/v1/objects/11");
      // 把API返回的数据存到res.locals(Express专门用来存中间件共享数据的地方)
      res.locals.artData = response.data;
      // 调用next,告诉Express可以执行下一个路由处理逻辑了
      next();
    } catch (error) {
      console.error('获取数据出错:', error);
      // 把错误传递给Express的全局错误处理中间件(如果有的话)
      next(error);
    }
  }
};

export default metAPI;

第二步:修复routes/met_route.js,从上下文里取数据并返回

'use strict';
import express from "express";
import metData from "../models/metData.js";

const router = express.Router();
router.get('/', metData.searchArt, (req, res) => {
    // 从res.locals里拿到之前存的API数据,发送给客户端
    res.send(res.locals.artData);
})

export default router;

另一种简化方案(直接在中间件里发响应)

如果你的路由逻辑不需要额外处理数据,也可以直接在searchArt里发送响应,省去后续的路由处理函数:

// models/metData.js 简化版
searchArt: async function(req, res) {
  try {
    const response = await axios.get("https://collectionapi.metmuseum.org/public/collection/v1/objects/11");
    // 直接在这里把数据发给客户端
    res.send(response.data);
  } catch (error) {
    console.error('获取数据出错:', error);
    // 给客户端返回错误状态码和提示
    res.status(500).send({ message: '获取艺术品数据失败', error: error.message });
  }
}

// routes/met_route.js 简化版
router.get('/', metData.searchArt);

这样修改后,Express会等待异步请求完成后再发送响应,就不会出现超时和空响应的问题啦~

备注:内容来源于stack exchange,提问作者James Johnson

火山引擎 最新活动