ReactJS问题:非Promise场景下无法从函数中获取数据
你遇到的是异步操作的经典陷阱!咱们先把问题拆解清楚:
service.getDistanceMatrix是一个异步函数——它不会立刻执行完内部的回调逻辑,而是先向服务端发送请求,等拿到响应后才会调用你传入的回调函数。但你写在函数外面的console.dir(location)和console.dir(location.distFinal)是同步执行的,这时候回调里的代码还没跑,distFinal自然还没被赋值,所以打印出来是undefined。
至于为什么console.dir(location)能看到distFinal属性?这是浏览器控制台的惰性求值特性:当你点开控制台里的对象时,回调已经执行完毕,对象已经被更新了,但在你执行console.dir(location)的那一刻,这个属性其实还不存在。
解决方案
所有依赖distance的逻辑,必须等异步操作完成后再执行,这里给你几种常用的处理方式:
1. 直接把逻辑放到回调函数内部(最简单直接)
把需要使用distance的代码,全部写到回调里status == 'OK'的分支中:
service.getDistanceMatrix({ origins: ["Waterloo ON"], destinations: destination, travelMode: 'DRIVING', avoidHighways: false, avoidTolls: false }, function(response, status){ if (status == 'OK') { var origins = response.originAddresses; var destinations = response.destinationAddresses; for (var i = 0; i < origins.length; i++) { var results = response.rows[i].elements; for (var j = 0; j < results.length; j++) { var element = results[j]; var distance = element.distance.text; var from = origins[i]; var to = destinations[j]; location.distFinal = distance; location.setState({ dist: distance }); // 在这里使用distance,或者调用处理它的函数 console.dir(location.distFinal); // 这里能拿到正确的值 processDistance(distance, from, to); // 比如调用专门的处理函数 } } } }) // 专门处理distance的函数 function processDistance(distance, from, to) { // 所有需要用distance的逻辑都写在这里 console.log(`从${from}到${to}的距离是${distance}`); }
2. 用Promise+async/await改写(更现代的写法)
如果你的环境支持ES6+,可以把回调式的函数包装成Promise,用async/await让代码看起来像同步逻辑:
// 先把getDistanceMatrix包装成Promise function fetchDistanceMatrix(options) { return new Promise((resolve, reject) => { service.getDistanceMatrix(options, (response, status) => { if (status === 'OK') { resolve(response); } else { reject(new Error(`请求失败:${status}`)); } }); }); } // 用async/await调用 async function getDistance() { try { const response = await fetchDistanceMatrix({ origins: ["Waterloo ON"], destinations: destination, travelMode: 'DRIVING', avoidHighways: false, avoidTolls: false }); // 提取distance并处理 const origins = response.originAddresses; const destinations = response.destinationAddresses; for (let i = 0; i < origins.length; i++) { const results = response.rows[i].elements; for (let j = 0; j < results.length; j++) { const element = results[j]; const distance = element.distance.text; location.distFinal = distance; location.setState({ dist: distance }); // 在这里使用distance console.dir(location.distFinal); } } } catch (err) { console.error('获取距离失败:', err); } } // 调用函数 getDistance();
额外注意:React setState的异步性
如果你用的是React,setState本身也是异步的,所以如果在setState后立刻打印location.state.dist,也可能拿不到最新值。这时候可以用setState的回调函数:
location.setState({ dist: distance }, () => { // 这个回调会在state更新完成后执行 console.log('更新后的距离:', location.state.dist); });
核心总结:异步操作的代码不会按顺序同步执行,所有依赖异步结果的逻辑,必须放在回调、Promise的then或者await之后。
内容的提问来源于stack exchange,提问作者its.david

