如何强制回调方法等待Google标记创建 [英] How to force callback method to wait for Google Markers creation

查看:93
本文介绍了如何强制回调方法等待Google标记创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Google地图库制作一个应用程序.我的问题是创建标记时出现了无法解释的延迟,或者我有一个看不见的异步问题.

I am making an app using the Google maps library. My problem is either there is an unexplicable delay in creating the Markers or I have an asynchronous problem I cannot see.

说明:该代码沿起点和终点之间的路线获取充电站的位置,为获取的每个返回站创建Google标记(采用Json格式),并将其推入数组中.稍后,应该使用这些标记(此处未包含)来计算具有中途停留的路线.

Explanation : the code fetches Electric Charging Stations Location along a route between a start and an end points, creates Google markers for each station the fetch returns (in Json format) and pushes them in an array. Later it is supposed to calculate a route with stopovers using those markers (not included here).

问题在于它会在完成创建标记之前启动计算方法.

The problem is it launches the calculation method before it finishes to create the markers.

为了协调结果,我不会一次获取所有结果.相反,我做了一个执行以下操作的循环:

In order to harmonize results I don't fetch all results at once. Instead I made a loop that does the following :

  1. 创建一条路线并从中提取一条编码的折线(用于URL)
  2. 获取结果
  3. 创建标记,将其设置在地图上,然后将其压入数组
  4. 在控制台中登录工作已完成("EV标记创建完成")

然后启动路由计算过程(在此由警报'calculateAndDisplayRoute方法调用)

Then it launches the route calculation process (here replaced by an alert 'calculateAndDisplayRoute method called)

但是实际上,循环结束并登录到控制台,但未创建最后一个标记,警报启动,并且只有在您看到标记出现在地图上之后.

But in reality the loop finishes and logs in console but the last markers are not created, the alert is launched and only after can you see the markers appear on the map.

您可以尝试以下代码段: https://codepen.io/reivilo85k/pen/wvowpab

You can try the following code snippet :https://codepen.io/reivilo85k/pen/wvowpab

这是有问题的代码(我不得不在代码笔中添加更多代码才能使其正常工作):

Here is the problematic code (I had to add more code in the codepen in order to make it work though) :

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);
        }
      })
    );
  }

推荐答案

正如我在评论中提到的那样,您的代码按预期工作,并且问题来自使用

As I mentioned in my comment your code works as expected and the issue comes from the use of alert() which at the time it is fired, blocks your browser from executing any further code — and more importantly — further UI rendering.

几乎所有对DOM有所作为的代码都可以很容易地重现这一点.

This is easily reproducible with almost any code that does something to the 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中但在之前之前(至少在我的浏览器中)将警报添加到DOM中后,会触发警报.

The alert is fired after the node has been added to the DOM but before the browser has rendered it (at least in my browser).

console.log()替换代码中的 alert(),并添加另一个 console.log('marker included')您在其中创建每个 google.maps.Marker()的地方都会显示事件的顺序是您期望的:

Replacing the alert() in your code with a console.log() and adding another console.log('marker added') where you create each google.maps.Marker() shows that the order of events is what you expected:

  1. (84)标记已添加
  2. 循环6之6
  3. EV标记创建完成
  4. calculateAndDisplayRoute方法称为

,但在浏览器完成呈现标记之前会触发 alert().

but the alert() is fired before the browser has finished rendering the markers.

您可能应该避免出于调试目的而使用 alert(),或者请谨慎使用,因为它可能会误导您.

You should probably avoid using alert() for debugging purposes, or use it carefully as it can be misleading.

这篇关于如何强制回调方法等待Google标记创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆