如何解决如何强制回调方法等待 Google 标记创建
我正在使用 Google 地图库制作应用程序。我的问题是在创建标记时出现了无法解释的延迟,或者我有一个我看不到的异步问题。
说明: 该代码沿起点和终点之间的路线获取充电站位置,为获取返回的每个站创建 Google 标记(采用 Json 格式)并将它们推送到数组中。稍后,它应该使用这些标记(此处不包括)计算具有中途停留的路线。
问题是它在完成标记创建之前启动计算方法。
为了统一结果,我不会一次获取所有结果。相反,我做了一个循环,执行以下操作:
- 创建路由并从中提取编码折线(用于 URL)
- 获取结果
- 创建标记,将它们设置在地图上并将它们推送到数组上
- 登录控制台完成工作('EV 标记创建完成')
然后启动路由计算过程(这里替换为alert 'calculateAndDisplayRoute 方法调用)
但实际上循环结束并登录控制台,但未创建最后一个标记,启动警报,只有在此之后您才能看到标记出现在地图上。
您可以尝试以下代码片段:https://codepen.io/reivilo85k/pen/wvowpab
这是有问题的代码(我必须在 codepen 中添加更多代码才能使其工作):
chargingPointsMarkers = [];
markerArray = [];
async callbackHandler(startEndPointsArray,calculateAndDisplayRoute): Promise<void> {
await this.setChargingStationsMarkers();
calculateAndDisplayRoute();
}
function calculateAndDisplayRoute() {
alert('calculateAndDisplayRoute method called')
}
async function setChargingStationsMarkers() {
const polylineMarkersArray = await createMarkersArray();
console.log('Polyline Markers created',polylineMarkersArray);
const baseUrl = 'URL REMOVED';
for (let j = 0; j < polylineMarkersArray.length - 1; j++) {
const origin = polylineMarkersArray[j].getPosition();
const destination = polylineMarkersArray[j + 1].getPosition();
const route = await createRoute(origin,destination);
const encodedPolyline = route.overview_polyline;
const queryUrl = baseUrl + '&polyline='+ encodedPolyline + '&distance=50';
await fetch(queryUrl)
.then((response) => response.json())
.then( async (data) => await createChargerPointMarkers(data))
.then (() => {
const k = j + 1;
const l = polylineMarkersArray.length - 1;
if (j === polylineMarkersArray.length - 2) {
console.log('loop ' + k + ' of ' + l);
console.log('EV markers creation finished');
}else{
console.log('loop ' + k + ' of ' + l);
}
});
}
}
async createChargerPointMarkers(jsonChargingPoints): Promise<void> {
// Convert the Json response elements to Google Markers,places them on the Map and pushes them to an array.
for (const item of jsonChargingPoints) {
const LatLng = new google.maps.LatLng(parseFloat(item.AddressInfo.Latitude),parseFloat(item.AddressInfo.Longitude));
const marker = await new google.maps.Marker({
position: LatLng,map: this.map,draggable: false,});
this.markerArray.push(marker);
this.chargingPointsMarkers.push(marker);
}
}
async createRoute(point1,point2): Promise<google.maps.DirectionsRoute> {
// Returns a Google DirectionsRoute object
const directionsService = new google.maps.DirectionsService();
const request = {
origin: point1,destination: point2,travelMode: google.maps.TravelMode.DRIVING,unitSystem: google.maps.UnitSystem.METRIC
};
return new Promise(resolve => directionsService.route(request,(result,status) => {
if (status === 'OK') {
resolve(result.routes[0]);
} else {
window.alert('Directions request failed due to ' + status);
}
})
);
}
解决方法
正如我在评论中提到的,您的代码按预期工作,问题来自于 alert()
的使用,它在被触发时会阻止您的浏览器执行任何进一步的代码——更重要的是——进一步的用户界面渲染。
这几乎可以使用任何对 DOM 执行某些操作的代码轻松重现。
const el = document.createElement("div");
const text = document.createTextNode("Hello world");
el.appendChild(text);
document.body.appendChild(el);
console.log('done');
alert('done');
警报在节点被添加到 DOM 之后但之前被浏览器渲染(至少在我的浏览器中)被触发。
将代码中的 alert()
替换为 console.log()
并在创建每个 console.log('marker added')
的位置添加另一个 google.maps.Marker()
表明事件的顺序符合您的预期:>
(84) marker added
loop 6 of 6
EV markers creation finished
calculateAndDisplayRoute method called
但是 alert()
在浏览器完成标记渲染之前被触发。
您可能应该避免将 alert()
用于调试目的,或者小心使用它,因为它可能会产生误导。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。