如何强制回调方法等待 Google 标记创建
How to force callback method to wait for Google Markers creation
我正在使用 Google 地图库制作应用程序。我的问题是在创建标记时存在莫名其妙的延迟,或者我有一个我看不到的异步问题。
说明:
该代码沿起点和终点之间的路线获取充电站位置,为每个充电站创建 Google 标记获取 returns(采用 Json 格式)并将它们推送到数组中.稍后它应该使用这些标记(此处未包括)计算具有中途停留的路线。
问题是它在完成创建标记之前启动了计算方法。
为了协调结果,我不会一次获取所有结果。相反,我做了一个循环来执行以下操作:
- 创建一条路线并从中提取一条编码折线(用于 URL)
- 获取结果
- 创建标记,将它们设置在地图上并将它们推送到数组
- 在控制台中登录,作业已完成 ('EV markers creation finished')
然后它启动路由计算过程(这里替换为一个警报 '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()
,它在被触发时会阻止您的浏览器执行任何进一步的代码——更重要的是——进一步 UI 渲染。
几乎任何对 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()
并在创建每个 google.maps.Marker()
的位置添加另一个 console.log('marker added')
表明事件的顺序符合您的预期:
(84) marker added
loop 6 of 6
EV markers creation finished
calculateAndDisplayRoute method called
但是 alert()
在浏览器完成标记渲染之前触发。
您可能应该避免使用 alert()
进行调试,或者谨慎使用它,因为它可能会产生误导。
我正在使用 Google 地图库制作应用程序。我的问题是在创建标记时存在莫名其妙的延迟,或者我有一个我看不到的异步问题。
说明: 该代码沿起点和终点之间的路线获取充电站位置,为每个充电站创建 Google 标记获取 returns(采用 Json 格式)并将它们推送到数组中.稍后它应该使用这些标记(此处未包括)计算具有中途停留的路线。
问题是它在完成创建标记之前启动了计算方法。
为了协调结果,我不会一次获取所有结果。相反,我做了一个循环来执行以下操作:
- 创建一条路线并从中提取一条编码折线(用于 URL)
- 获取结果
- 创建标记,将它们设置在地图上并将它们推送到数组
- 在控制台中登录,作业已完成 ('EV markers creation finished')
然后它启动路由计算过程(这里替换为一个警报 '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()
,它在被触发时会阻止您的浏览器执行任何进一步的代码——更重要的是——进一步 UI 渲染。
几乎任何对 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()
并在创建每个 google.maps.Marker()
的位置添加另一个 console.log('marker added')
表明事件的顺序符合您的预期:
(84) marker added
loop 6 of 6
EV markers creation finished
calculateAndDisplayRoute method called
但是 alert()
在浏览器完成标记渲染之前触发。
您可能应该避免使用 alert()
进行调试,或者谨慎使用它,因为它可能会产生误导。