无法访问函数返回对象的属性?打印对象正常但属性值为undefined
问题根源:异步操作的执行顺序坑了你!
兄弟,你遇到的这个问题我见太多了——核心原因就是google.maps.Geocoder.geocode()是个异步方法!它不会像普通同步代码那样,调用完立刻给data赋值,而是先把请求发出去,然后直接跳过回调函数继续执行你的其他代码,等谷歌服务器返回地理编码结果后,才会回头执行回调里的赋值逻辑。
给你拆解下代码的实际执行顺序:
- 创建
geocoder实例,初始化空的data对象 - 调用
geocoder.geocode(),向谷歌发送地理编码请求 - 直接跳出当前函数(或者执行你后面访问
data.prop的代码)——这时候data还是个空对象,属性根本没被赋值! - 过了几百毫秒(甚至更久),谷歌的响应回来了,才会执行回调里的
data.longitude = ...这些赋值操作
至于你打印整个data对象时能看到属性,是因为浏览器控制台会“实时更新”对象内容(其实是你展开对象的时候才去读取最新值),但你同步访问data.prop的那一刻,属性还没被创建,自然就返回undefined了。
解决方案:用Promise/async-await驯服异步逻辑
要解决这个问题,最优雅的方式是把异步操作封装成Promise,这样就能确保你在拿到数据之后再去访问属性:
function geocodeAddress(value) { return new Promise((resolve, reject) => { const geocoder = new google.maps.Geocoder(); geocoder.geocode({'address': value}, function(results, status) { if (status === 'OK') { const locationData = { longitude: results[0].geometry.location.lng(), latitude: results[0].geometry.location.lat() }; resolve(locationData); // 请求成功,返回数据 } else { reject(new Error(`地理编码失败:${status}`)); // 请求失败,返回错误信息 } }); }); } // 调用方式1:用async/await(推荐,代码更像同步逻辑) async function fetchLocation() { try { const data = await geocodeAddress("你的目标地址"); console.log(data.longitude); // 这里就能正常拿到值了! console.log(data.latitude); // 在这里做你需要的后续操作 } catch (err) { console.error(err.message); } } // 调用方式2:用.then()链式调用(兼容旧环境) geocodeAddress("你的目标地址") .then(data => { console.log(data.longitude); console.log(data.latitude); }) .catch(err => console.error(err.message));
简单粗暴的替代方案:在回调内部处理数据
如果你不想折腾Promise,也可以直接把需要用到data的逻辑全部放到回调函数里面——这样就能保证代码是在属性赋值完成后才执行的:
function geocodeAddress(value) { const geocoder = new google.maps.Geocoder(); geocoder.geocode({'address': value}, function(results, status) { if (status === 'OK') { const data = { longitude: results[0].geometry.location.lng(), latitude: results[0].geometry.location.lat() }; // 所有需要用data的逻辑都写在这里 console.log(data.longitude); // 正常输出 console.log(data.latitude); processLocation(data); // 传给其他处理函数 } else { console.error(`地理编码失败:${status}`); } }); } function processLocation(location) { // 在这里处理你的位置数据 console.log("处理后的经度:", location.longitude); }
总结一下:异步操作的结果绝对不能在回调外部同步获取,必须等异步请求完成后再处理数据——Promise+async/await是现在处理异步逻辑最清晰、最易维护的方式,建议优先用这个方案!
内容的提问来源于stack exchange,提问作者Umar Gora
相关产品推荐
相关产品推荐

