使用async/await调Google Maps API后Ajax提交控制器接收坐标距离为null
问题根源
- 你封装的异步Promise
resolve时机错误:调用Google Maps API后不等异步回调返回就直接resolve,导致await执行完成时,Lat、Lng、Distance三个隐藏域还没被赋值,表单序列化时拿到的就是初始空值 - 额外的不匹配问题:你设置了请求头
contentType = "application/json; charset=utf-8",但提交数据用的是serialize()生成的表单编码格式,两者格式不统一,也可能导致后端参数绑定失败
修复方案
1. 修正GetLatLngGoogle的Promise逻辑
把resolve放到geocode的回调函数里,等拿到坐标赋值到隐藏域后再标记异步完成:
async function GetLatLngGoogle(address) { return new Promise((resolve) => { geocoder = new google.maps.Geocoder(); geocoder.geocode({ 'address': address }, function (results, status) { $("#Lat").val(results[0].geometry.location.lat()); $("#Lng").val(results[0].geometry.location.lng()); resolve('resolved'); // 赋值完成后再resolve }); }); };
2. 修正GetDistance的异步逻辑
把路线查询后的回调逻辑整合到Promise里,等距离计算完成赋值到隐藏域后再resolve,原来的RenderCustomDirections和computeTotalDistance可以直接删除:
async function GetDistance() { return new Promise((resolve) => { var center = new google.maps.LatLng(40.71620968890981, -74.08542546242037); var clientPosition = new google.maps.LatLng(40.70550895916085, -74.0791867502397); var storePosition = { lat: 40.71620968890981, lng: -74.08542546242037 }; directionsService = new google.maps.DirectionsService(); directionsDisplay = new google.maps.DirectionsRenderer(); var route = { origin: storePosition , destination: clientPosition, travelMode: google.maps.TravelMode.DRIVING }; directionsService.route(route, function(response, status) { if (status == google.maps.DirectionsStatus.OK) { start = new Object(); end = new Object(); var legs = response.routes[0].legs; for (i = 0; i < legs.length; i++) { if (i == 0) { start.latlng = legs[i].start_location; start.address = legs[i].start_address; } end.latlng = legs[i].end_location; end.address = legs[i].end_address; } directionsDisplay.setDirections(response); // 计算距离赋值 let total = 0; let timeTotal = 0; const myroute = response.routes[0]; if (myroute) { for (let i = 0; i < myroute.legs.length; i++) { total += myroute.legs[i].distance.value; timeTotal += myroute.legs[i].duration.value; } total = total / 1000; timeTotal = timeTotal / 60; $('#Distance').val(total.toFixed(1)); } resolve('resolved'); // 所有赋值完成后再resolve } else { alert(status); resolve('error'); } }); }); };
3. 修正Ajax请求的格式不匹配问题
删掉多余的contentType配置,用默认的表单编码格式适配serialize()的输出:
function AddAddress() { var options = {}; options.type = "POST"; options.url = "/api/AddAddress"; options.dataType = "JSON"; options.cache = false; options.async = true; options.data = $('#formAdd').serialize(); // 表单序列化默认是x-www-form-urlencoded格式,不需要额外设置json类型的contentType options.beforeSend = function (xhr) { xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val()); }; options.success = function (data) { }; options.error = function () { }; $.ajax(options); };
修改完成后三个隐藏域会在赋值完成后才执行表单序列化提交,后端就能正常拿到参数。
内容的提问来源于stack exchange,提问作者Guto Barroso
相关产品推荐
相关产品推荐

