Angular 6 Область подписки - переменные не могут быть назначены - PullRequest
0 голосов
/ 12 марта 2019

У меня есть компонент карты, использующий API mapbox, который зависит от продольных и широтных координат, возвращаемых геокодером.

Существует служба, которая вызывает конечную точку с некоторыми параметрами. Я подписываюсь на этот сервис и использую функцию стрелки, как видно из кода ниже. Хотя я ожидаю, что ответ был назначен this.geocodeResponse, а также соответствующим this.longitude и this.latitude, эти переменные остаются пустыми вне области действия функции. Я знаю это, потому что я получаю этот ответ от брата ERROR Error: "Invalid LngLat object: (NaN, NaN)". Я подтвердил этот результат, зарегистрировав ответы на console.log и подтвердив, что три ответа остаются пустыми.

Я знаю, что служба работает, потому что она была протестирована и дает действительный ответ в другом месте.

Вот соответствующий код:

import { Component, OnInit, ViewChild, ElementRef, Input } from "@angular/core";

import mapboxgl from "mapbox-gl";

import { GeocodingService } from "../geocoding.service";
import { environment } from "../../../environments/environment";

@Component({
  selector: "app-dynamic-map",
  templateUrl: "./dynamic-map.component.html",
  styleUrls: ["./dynamic-map.component.css"]
})
export class DynamicMapComponent implements OnInit {
  @Input() queryString: String
  geocodeResponse: any;
  longitude: string;
  latitude: string;

  map: mapboxgl.Map;
  @ViewChild("mapElement") mapElement: ElementRef;
  constructor(private geocodingService: GeocodingService) {}

  ngOnInit() {
    mapboxgl.accessToken = environment.mapbox.accessToken;

    this.geocodingService.getGeoCords(this.queryString).subscribe(response => {
      this.geocodeResponse = response;
      this.longitude = this.geocodeResponse.features[0].bbox[0],
      this.latitude = this.geocodeResponse.features[0].bbox[1]
  });
  }

  /* Given a query string, get the first result of a places query from api and pass to
   * the dynamic map centering on coordinates */
  ngAfterViewInit() {

    /* THESE REMAIN UNASSIGNED HERE */
    console.log(this.geocodeResponse)
    console.log(this.longitude)
    console.log(this.latitude)

    this.map = new mapboxgl.Map({
      container: this.mapElement.nativeElement,
      style: "mapbox://styles/mapbox/streets-v9",
      center: [this.longitude, this.latitude],
      zoom: 12
    });
  }
}

Я знаю, что проблема заключается в подписке на услугу. Я не могу полностью понять, как Angular обрабатывает подписку и область видимости переменной ответа.

Ожидаемое поведение будет непустыми переменными вне ответа подписки. Более того, я наблюдал такое поведение в отладчике firefox, но без использования тегов в отладчике переменные остаются неназначенными.

Я могу предоставить дополнительный код и вывод журнала при необходимости. Пожалуйста, будьте конкретны в том, что необходимо для диагностики проблемы. Кроме того, хотя явное решение проблемы приятно, мне бы очень хотелось понять, почему эта проблема возникает, потому что у меня есть несколько других компонентов, у которых есть похожие проблемы.

1 Ответ

0 голосов
/ 12 марта 2019

Проблема с компонентом заключается в том, что он опирается на данные, которые он сначала должен получить от асинхронной операции.Есть 2 распространенных способа обойти это:

  1. Инициализируйте критические значения значениями по умолчанию в вашем компоненте.Когда компонент получит ответ от асинхронного вызова, значения будут обновлены.
  2. Используйте индикатор в компоненте, чтобы проверить, был ли обработан асинхронный ответ или нет.Проверьте эти значения, где это применимо при любых вызовах методов машинописного текста, и скройте HTML в шаблоне, где html полагается на значения из службы.

Вот некоторый код, который иллюстрирует вышеупомянутые пункты.Не весь ваш код дублируется ниже.

Значения по умолчанию

export class DynamicMapComponent implements OnInit {
  longitude: string;
  latitude: string;

  constructor(private geocodingService: GeocodingService) {
    this.longitude = '0';
    this.latitude = '0';
  }

  ngOnInit() {
    mapboxgl.accessToken = environment.mapbox.accessToken;

    this.geocodingService.getGeoCords(this.queryString).subscribe(response => {
      this.geocodeResponse = response;
      this.longitude = this.geocodeResponse.features[0].bbox[0];
      this.latitude = this.geocodeResponse.features[0].bbox[1];
    });
  }

Индикатор

export class DynamicMapComponent implements OnInit {
  longitude: string;
  latitude: string;
  isInitialized: boolean = false;

  constructor(private geocodingService: GeocodingService) {
  }

  ngOnInit() {
    mapboxgl.accessToken = environment.mapbox.accessToken;

    this.geocodingService.getGeoCords(this.queryString).subscribe(response => {
      this.geocodeResponse = response;
      this.longitude = this.geocodeResponse.features[0].bbox[0];
      this.latitude = this.geocodeResponse.features[0].bbox[1];
      this.isInitialized = true;
    });
  }

dynamic-map.component.html

<div *ngIf="isInitialized">
  <p>dependent html here</p>
</div>

См. Также Как вернуть ответ от асинхронного вызова? для получения дополнительной информации об асинхронных вызовах в javascript.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...