Razor Pages中JavaScript异步坐标传入Google Maps初始化的方法
问题根因
你目前在控制台能打印出正确的经纬度,但外层拿不到值的核心原因,是异步代码的执行时序不匹配、Promise传递链路断裂导致的:
- 原有的
getLatitude/getLongitude函数没有向外抛出axios返回的Promise对象,你在.then回调里写的return lat/lng,只是给当前异步回调返回了值,外层调用链路根本捕获不到这个结果——控制台打印正常,只是因为console.log写在这个异步回调的内部执行链路里 initMap是同步执行的函数,运行到取值代码时,Geocode的网络请求还在等待响应,代码就已经提前把getLatitude()/getLongitude()的返回值(实际是undefined)赋给了latitude、longitude变量- 两个函数逻辑完全重复,会对同一个地址发送两次相同的Geocode请求,平白消耗Google API的免费配额
优化实现方案
- 合并重复的坐标获取逻辑,封装为统一的、返回Promise的地理编码请求函数
- 修改
initMap的执行逻辑,等待坐标异步加载完成后,再执行地图初始化
第一步:替换重复的两个坐标获取函数
去掉重复的getLatitude、getLongitude,用统一的异步请求函数替代:
async function getGeocodeCoordinates(address) { try { const res = await axios.get('https://maps.googleapis.com/maps/api/geocode/json', { params: { address: address, key: 'xxxxxx' } }) // 直接返回完整的经纬度对象,不需要拆分 return res.data.results[0].geometry.location } catch (err) { console.error('地理编码请求异常:', err) } }
第二步:修改initMap的异步等待逻辑
把原来同步取值的部分,改成等待坐标加载完成后再初始化地图:
async function initMap() { // 直接在当前作用域获取需要的查询地址,避免全局变量污染 const searchedAddress = @Html.Raw(Json.Serialize(ViewData["searchString"])); // 等异步拿到坐标再继续执行 const location = await getGeocodeCoordinates(searchedAddress) // 增加兜底判断,避免地址解析失败时地图初始化报错 if (!location) { alert('无法解析您输入的地址,请检查后重试') return } const mapOptions = { zoom: 15, center: location } const map = new google.maps.Map(document.getElementById('map'), mapOptions) const marker = new google.maps.Marker({ position: location, map: map }) }
注意事项
- 因为
initMap现在是异步函数,需要确保Google Maps JS API的加载回调能正确指向这个初始化方法,不要因为脚本加载时序问题导致找不到入口 - 原代码中全局赋值的
searchedAddress变量没有用let/const声明,容易引发变量冲突,修改后的逻辑把地址获取放到了实际使用的作用域内,规避了这个问题 - 注意Geocoding API的免费调用配额,单次请求拿到完整坐标的方案,相比原来两次重复请求可以节省一半的配额消耗
内容的提问来源于stack exchange,提问作者BenTen
相关产品推荐
相关产品推荐

