首页 > 解决方案 > 使用 Google Maps 地理编码服务时,Angular 中使用输入绑定的子组件速度很慢

问题描述

我有一个使用 Google Maps API 中的 Angular 和 google.maps.Geocoder() 的 MEAN 应用程序。它显示了一张地图,它可以搜索/可视化地址。我在“地图”组件中执行此操作,一切正常。我有一个显示结果的子“表单”组件。但是,在表单组件检测到更改并显示之前需要几秒钟(有时长达 20 秒钟)。怎么来的?

可能的原因:

也许主 JS 线程正忙于我的请求,阻止了对子组件的更新。在浏览器的网络日志中,我看到一个名为“websocket”的文件(我认为搜索时会创建一个类似的文件),时间为“待处理”并警告“请求尚未完成”。我想知道为什么这会阻止 Angular(特别是对子组件的更新)以及如何避免这种情况。

更多细节:

父子通过输入绑定进行通信,我也使用 ngOnChanges 进行数据交换。为简单起见,我有一个测试,我只是从地图(父组件)传递到表单(子组件)一个“formBoolean”布尔值。布尔值在地理编码搜索后显示在表单中,但如上所述,这需要几秒钟才能发生。

注意,当我从 findLocation() 回调中删除地理编码时,子组件会快速显示布尔值的变化。这就是为什么我认为地理编码“使角度变慢”


我的简化代码如下所示应该可以说明问题。

index.html 使用我的 API 密钥(未显示)指向 maps.googleapis.com。

map.component.ts(父组件):

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ViewChild } from '@angular/core';


@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})

export class MapComponent implements OnInit {
  ngOnInit() {
    //Here I omit mapProp in the call to Map() above
    this.map = new google.maps.Map(this.gmapElement.nativeElement); 
  }

  @ViewChild('gmap') gmapElement: any;
  map: google.maps.Map;
  geocoder: any;
  formChanged: boolean = false;

  findLocation() {  
    if (!this.geocoder) this.geocoder = new google.maps.Geocoder();
    this.geocoder.geocode({
      'address': '1116 S Long Beach Blvd, Compton, CA 90221, USA',
      'componentRestrictions': {country: 'US'} //I use country restriction
      }, (results,  status) => {
        //I omit how I manipulate the results object, place a marker on the map, and pass data to child. 
        //The marker on the map appears immediately. I can console.log results
        //For this example I just pass to the form component the followin boolean:
        this.formChanged = !this.formChanged;
      }

}

map.component.html(父组件):

<!--For simplicity i just show the button and the binding to the child component--> 
<button type="submit" class="btn btn-primary" (click)="findLocation()">Search</button>

<app-form [formChanged]="formChanged" [formResult]="formResult"></app-form>

form.component.ts(子组件):

import { Component, Input } from '@angular/core';
import { OnChanges, SimpleChanges, SimpleChange } from '@angular/core';

@Component({
  selector: 'app-form',
  templateUrl: '{{formChanged}}',
  styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit, OnChanges {
  @Input('formResult') formResult: Store;
  @Input('formChanged') formChanged: boolean;

  constructor(private storeService: StoreService){}

  ngOnChanges(changes: SimpleChanges){
    console.log('form - ngOnChanges',changes)
  }
}

如前所述,地理编码有效,但可能需要 20 秒才能更新子“表单”组件,并且我在控制台中看到了更改

标签: angulargoogle-maps-api-3inputbinding

解决方案


您可以使用 Promise 将可能阻止主线程“查找位置”的繁重操作移至异步调用。

findLocation() {  
    if (!this.geocoder) this.geocoder = new google.maps.Geocoder();
    return new Promise((resolve, reject)=>{
       this.geocoder.geocode({
         'address': '1116 S Long Beach Blvd, Compton, CA 90221, USA',
         'componentRestrictions': {country: 'US'} //I use country restriction
         }, (results,  status) => {
            //I omit how I manipulate and pass data to child. For this exampl
            just pass the followin boolean:
            this.formChanged = !this.formChanged;
            resolve(true);
          });
     });

}

推荐阅读