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

全局变量在函数外显示undefined?API跨调用数据传递异常

问题原因

这是典型的异步操作执行顺序问题。https.get属于异步方法,发起请求后不会阻塞后续代码运行:你定义的console.log和url2会在第一个API的响应返回前就执行,此时latitude和longitude还没被赋值,自然处于undefined状态。只有当API响应完成后,response.on("data")里的回调函数才会触发,给这两个变量赋值。

解决方案

下面提供几种可行的修复方式:

方式1:嵌套回调(最直接的修改)

将第二个API的调用逻辑放到第一个API的回调内部,确保拿到坐标后再执行后续操作:

var latitude, longitude;
var cityn = req.body.cityname;
const appid = "...";
var unit = "metric";

const url1 = "https://api.openweathermap.org/geo/1.0/direct?q=" + cityn + "&limit=5&appid=" + appid;

https.get(url1, function(response) {
  // 注意:API响应可能分块返回,需要拼接完整数据
  let rawData = "";
  response.on("data", function(chunk) {
    rawData += chunk;
  });

  response.on("end", function() {
    const CityDetails = JSON.parse(rawData);
    latitude = CityDetails[0].lat;
    longitude = CityDetails[0].lon;
    console.log(latitude); // 此时已赋值
    console.log(longitude); // 此时已赋值

    // 在这里发起第二个API请求
    const url2 = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${appid}&units=${unit}`;
    https.get(url2, function(weatherResponse) {
      let weatherRawData = "";
      weatherResponse.on("data", function(chunk) {
        weatherRawData += chunk;
      });
      weatherResponse.on("end", function() {
        const weatherDetails = JSON.parse(weatherRawData);
        // 处理天气数据的后续逻辑
      });
    });
  });
});

方式2:Promise封装(避免回调地狱)

把异步请求封装为Promise,让异步逻辑更清晰:

var cityn = req.body.cityname;
const appid = "...";
var unit = "metric";

// 封装获取城市坐标的Promise
function getCityCoords(cityName) {
  return new Promise((resolve, reject) => {
    const url1 = `https://api.openweathermap.org/geo/1.0/direct?q=${cityName}&limit=5&appid=${appid}`;
    https.get(url1, function(response) {
      let rawData = "";
      response.on("data", chunk => rawData += chunk);
      response.on("end", () => {
        try {
          const cityData = JSON.parse(rawData);
          resolve({
            lat: cityData[0].lat,
            lon: cityData[0].lon
          });
        } catch (err) {
          reject(err);
        }
      });
      response.on("error", reject);
    });
  });
}

// 封装获取天气数据的Promise
function getWeatherData(lat, lon) {
  return new Promise((resolve, reject) => {
    const url2 = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${appid}&units=${unit}`;
    https.get(url2, function(response) {
      let rawData = "";
      response.on("data", chunk => rawData += chunk);
      response.on("end", () => {
        try {
          const weatherData = JSON.parse(rawData);
          resolve(weatherData);
        } catch (err) {
          reject(err);
        }
      });
      response.on("error", reject);
    });
  });
}

// 链式调用处理异步流程
getCityCoords(cityn)
  .then(coords => {
    console.log(coords.lat, coords.lon);
    return getWeatherData(coords.lat, coords.lon);
  })
  .then(weatherInfo => {
    // 处理最终的天气数据
    console.log(weatherInfo);
  })
  .catch(err => {
    console.error("请求出错:", err);
  });

方式3:async/await(最简洁的写法)

基于Promise封装,用async/await让异步代码看起来像同步代码:

var cityn = req.body.cityname;
const appid = "...";
var unit = "metric";

// 复用上面定义的getCityCoords和getWeatherData函数

async function fetchCityWeather() {
  try {
    const coords = await getCityCoords(cityn);
    console.log(coords.lat, coords.lon);
    const weatherInfo = await getWeatherData(coords.lat, coords.lon);
    // 处理天气数据的业务逻辑
    console.log(weatherInfo);
  } catch (err) {
    console.error("请求异常:", err);
  }
}

// 执行异步函数
fetchCityWeather();

注意:原代码中直接解析response.on("data")的回调参数可能会出现JSON解析错误,因为API响应可能分块返回,上面的方案都处理了这个问题,确保拼接完整数据后再解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:10:33