首页 > 解决方案 > 为什么我的 *ngFor 指令没有立即呈现?

问题描述

晚上好,

我正在开发一个 Angular 组件,但遇到了一个我不明白的错误。我正在尝试在我的组件上实现一个谷歌地图,所以我编写了一个从谷歌 API 检索 som 坐标的服务。

一切正常,而不是一件事。在组件从 addressRecommendations$ 流中接收到新值后,我的模板中的 *ngFor 指令需要大约 25 秒来呈现响应。我有点困惑,因为另一个 observable (tst$) 立即呈现。

绿色:请求发送,黄色:收到响应,红色:响应呈现 绿色:请求发送,黄色:收到响应,红色:响应呈现

import { Injectable, Type } from '@angular/core';
import { ArgumentOutOfRangeError, BehaviorSubject } from 'rxjs';
import {  } from '@angular/google-maps'

export class Address {
  public get addressString (): string {
    return `${this.street} ${this.number}, ${this.postalCode} ${this.place}`;
  }

  constructor(
    public street: string,
    public number: number,
    public postalCode: string,
    public place: string,
    public geo: google.maps.LatLngLiteral
  ){
    if(!(street && number && postalCode && place && geo))
      throw(new ArgumentOutOfRangeError());
  }
}

@Injectable({
  providedIn: 'root'
})
export class MapService {
  public addressRecomendations$: BehaviorSubject<Address[]> = new BehaviorSubject([]);
  public tst$: BehaviorSubject<string[]> = new BehaviorSubject([]);

  constructor() { 
  }
  
  public getPlaces(query: string, map: google.maps.Map = undefined) {
    if (!map)
      map = new google.maps.Map(document.createElement("span"));
    
    navigator.geolocation.getCurrentPosition(
      _currentLocation => {
        this.executePlacesQuery(query, map, {
          lat: _currentLocation.coords.latitude,
          lng: _currentLocation.coords.longitude
        })
      },
      notFound => {
        this.executePlacesQuery(query, map)
      }
    );

  }

  public executePlacesQuery(query: string, map: google.maps.Map, location: google.maps.LatLngLiteral = undefined) {
    let placesService = new google.maps.places.PlacesService(map);
    
    placesService.findPlaceFromQuery(
      {query, fields: ["place_id"]}, 
      (results: google.maps.places.PlaceResult[] | null, status: google.maps.places.PlacesServiceStatus) => {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
          let foundPlaces: Array<string> = [];

          results.forEach(result => {
            placesService.getDetails({placeId: result.place_id}, place => {
            })
            foundPlaces.push(result.place_id)
          });
          
          this.getAddresses(foundPlaces);
        } else {
          this.addressRecomendations$.error(status);
        }
      }
    )
  }


  private getAddresses(placeIds: string[]) {
    let geocoder: google.maps.Geocoder = new google.maps.Geocoder(); 
    let addresses: Array<Address> = [];
    let awaited = placeIds.length;
    let street: string;
    let place: string;
    let number: number;
    let postalCode: string;
    let geo: google.maps.LatLngLiteral;

    placeIds.forEach(placeId => {
      geocoder.geocode({placeId}, (results) => {
        results.forEach(result => {
          result.address_components.forEach(address_component => {
            if (address_component.types.includes("street_number")) {
              number = Number.parseInt(address_component.long_name); 
            }
            if (address_component.types.includes("locality")) {
              place = address_component.long_name; 
            }
            if (address_component.types.includes("postal_code")) {
              postalCode = address_component.long_name; 
            }
            if (address_component.types.includes("route")) {
              street = address_component.long_name; 
            }
          })
          geo = result.geometry.location.toJSON();
          try {
            addresses.push(new Address(street, number, postalCode, place, geo));
          } catch { /*ignore*/}
        });
  
        this.addressRecomendations$.next(addresses);
      });
    });
  }

  public emit(){
    this.tst$.next(["sodnfosnd", "sidhfuisd"]);
  }
}



<p *ngFor="let item of this.service.addressRecomendations$ | async">{{item}}</p>
<p *ngFor="let item of this.service.tst$ | async">{{item}}</p>
<button (click)="this.race()">Load</button>
import { Component, OnInit } from '@angular/core';
import { MapService } from '../map/map.service';

@Component({
  selector: 'addressmaintenance-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
  constructor(public service: MapService) { }

  ngOnInit(): void {
    this.service.addressRecomendations$.subscribe(x => {console.log(new Date().toLocaleTimeString())})
  }

  public race() {
    this.service.emit()
    this.service.getPlaces("edeka");
  }
}

标签: angular

解决方案


推荐阅读