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

基于OpenWeatherAPI的天气应用:Geocode属性调用显示Undefined问题

问题根源:异步操作的执行时机问题

你遇到的这个undefined问题,本质是异步代码的执行顺序导致的:

Geocode类的构造函数里调用了getLatLong()这个异步方法,但构造函数本身不能是异步函数。当你执行new GeoCode("toronto")时,构造函数会立刻完成,但getLatLong里的axios请求还在后台运行——这时候你马上访问geocode.lat和geocode.lon,这两个属性还没被赋值,自然是undefined。而稍后console.log(geocode)时,浏览器/Node.js会异步更新对象的显示,所以你能看到已经赋值后的完整属性。


解决方案:控制异步操作的执行时机

下面提供两种优雅的解决方式,你可以根据自己的代码风格选择:

方案一:给Geocode类添加初始化方法,外部await完成

修改geocode.js:

import axios from "axios";
export default class Geocode{
 constructor(city){
 this.city = city;
 // 不在构造函数里直接调用异步方法,把初始化控制权交给外部
 }

 // 新增异步初始化方法
 async init(){
 try{
 const res = await axios(`https://us1.locationiq.com/v1/search.php?key=${key}&q=${this.city}&format=json`);
 // 用parseFloat替代JSON.parse,更适合处理数字字符串
 this.lat = parseFloat(res.data[0].lat);
 this.lon = parseFloat(res.data[0].lon);
 }catch(err){
 console.log(err)
 }
 }
}

修改index.js:

用async函数包裹整个应用逻辑,等待Geocode初始化完成后再创建Search实例:

import Search from "./models/search";
import GeoCode from "./models/geocode";

async function initApp() {
 const geocode = new GeoCode("toronto");
 await geocode.init(); // 等待地理编码请求完成,确保lat和lon已赋值
 const weather = new Search(geocode.lat, geocode.lon);
 await weather.getResults(); // 可选:如果需要等待天气请求完成再打印结果
 console.log(geocode);
 console.log(weather);
}

// 启动应用
initApp();

方案二:使用静态异步工厂方法创建Geocode实例

这种方式更符合异步代码的最佳实践,直接返回一个已经初始化完成的Geocode实例:

修改geocode.js:

import axios from "axios";
export default class Geocode{
 // 构造函数只负责赋值,不处理异步逻辑
 constructor(city, lat, lon){
 this.city = city;
 this.lat = lat;
 this.lon = lon;
 }

 // 静态异步方法,负责请求数据并创建实例
 static async create(city){
 try{
 const res = await axios(`https://us1.locationiq.com/v1/search.php?key=${key}&q=${city}&format=json`);
 const lat = parseFloat(res.data[0].lat);
 const lon = parseFloat(res.data[0].lon);
 return new Geocode(city, lat, lon);
 }catch(err){
 console.log(err);
 throw err; // 抛出错误,让外部可以捕获处理
 }
 }
}

修改index.js:

import Search from "./models/search";
import GeoCode from "./models/geocode";

async function initApp() {
 try {
 // 直接获取已经完成地理编码的实例
 const geocode = await GeoCode.create("toronto");
 const weather = new Search(geocode.lat, geocode.lon);
 await weather.getResults();
 console.log(geocode);
 console.log(weather);
 } catch (err) {
 console.error("应用初始化失败:", err);
 }
}

initApp();

额外优化点
  • 你原本用JSON.parse(res.data[0].lat)是多余的,API返回的经纬度是字符串格式的数字,用parseFloat()更高效准确。
  • Search类同样存在异步问题:如果不await weather.getResults(),直接打印weather的话,result属性也会是undefined,所以建议也等待天气请求完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 15:52:52