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

Express+Axios调用OpenWeatherMap API遇连接拒绝及响应头错误求助

我来帮你拆解这两个问题,都是代码里的小细节导致的:

1. Error: connect ECONNREFUSED 127.0.0.1:80 问题

这个错误的核心原因是你的OpenWeatherMap API URL写错了——少了协议后的双斜杠!原代码里写的是http:api.openweathermap.org/...,正确的格式应该是http://api.openweathermap.org/...(更推荐用HTTPS,改成https://更安全)。

因为缺少//,Axios会把这个URL当成相对路径处理,默认请求本地服务器的80端口,这就导致了连接被拒绝的错误。而浏览器访问时会自动补全协议后的双斜杠,所以能正常返回数据,但Axios不会做这个自动补全,必须手动写对完整URL。

修正后的getWeather函数URL应该是:

url:`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${process.env.WAPI}`

2. Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client 问题

这个错误是因为你的路由逻辑里,同一个请求被发送了两次响应。

看你的路由代码:

if (lat && lon) { 
  // ... 这里会执行res.json(...)返回响应
} 
res.send("no location specified") 

当lat和lon存在时,你先发送了res.json()响应,但代码不会停止执行,会继续走到后面的res.send(),这就违反了HTTP协议一个请求对应一个响应的规则,导致报错。

解决方法很简单,有两种可选方案:

方案一:用return终止后续代码执行

app.get("/", cors(), async (req, res) => { 
  const lat: number = + req.query.lat; 
  const lon: number = + req.query.lon; 
  if (lat && lon) { 
    const entry = cach.filter(e => e.lat === lat && e.lon === lon); 
    if (entry.some(e => (Date.now() - e.last_updated < 36000000))) { 
      return res.json(entry[0]); // 加上return,阻止后续代码执行
    } else { 
      return res.json(await getWeather(lat, lon)); // 同样加return
    } 
  } 
  res.send("no location specified") 
}); 

方案二:用else分支包裹默认响应

app.get("/", cors(), async (req, res) => { 
  const lat: number = + req.query.lat; 
  const lon: number = + req.query.lon; 
  if (lat && lon) { 
    const entry = cach.filter(e => e.lat === lat && e.lon === lon); 
    if (entry.some(e => (Date.now() - e.last_updated < 36000000))) { 
      res.json(entry[0]); 
    } else { 
      res.json(await getWeather(lat, lon)); 
    } 
  } else { // 把默认响应放到else分支里
    res.send("no location specified") 
  }
}); 

额外小建议

你的getWeather函数里的catch块只打印了错误,但没有把错误信息反馈给客户端,而且缓存逻辑里没有把新获取的数据加入缓存(这样缓存永远不会更新)。可以优化一下:

async function getWeather(lat: number, lon: number) { 
  try { 
    const res = await axios({ 
      url:`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${process.env.WAPI}`, 
      method:"GET" 
    }); 
    const data = res.data; 
    // 返回带缓存时间的结构,方便后续缓存判断
    return {
      lat,
      lon,
      last_updated: Date.now(),
      ...data
    };
  } catch (error){ 
    console.error('获取天气数据失败:', error);
    // 抛出错误,让路由层处理并返回给客户端
    throw error;
  }
}

然后在路由里加上错误捕获,避免服务器崩溃:

app.get("/", cors(), async (req, res) => { 
  try {
    const lat: number = + req.query.lat; 
    const lon: number = + req.query.lon; 
    if (lat && lon) { 
      const entry = cach.filter(e => e.lat === lat && e.lon === lon); 
      if (entry.some(e => (Date.now() - e.last_updated < 36000000))) { 
        return res.json(entry[0]); 
      } else { 
        const weatherData = await getWeather(lat, lon);
        // 将新数据加入缓存
        cach.push(weatherData);
        return res.json(weatherData); 
      } 
    } 
    res.send("no location specified") 
  } catch (err) {
    res.status(500).json({error: '获取天气数据失败,请稍后重试'});
  }
}); 

内容的提问来源于stack exchange,提问作者JohanRH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:41:03