У меня есть компонент карты, использующий API-интерфейс mapbox, который зависит от долготных и широтных координат, возвращаемых геокодером.
Есть служба, которая вызывает конечную точку с некоторыми параметрами. Я подписываюсь на эту услугу и использую функцию стрелки, как показано в коде ниже. Хотя я ожидаю, что ответ будет назначен this.geocodeResponse, а также соответствующим this.longitude и this.latitude, эти переменные остаются пустыми вне области действия функции. Я знаю это, потому что получаю этот ответ от браузера ERROR Error: "Invalid LngLat object: (NaN, NaN)". Я подтвердил этот результат, зарегистрировав ответы в console.info и убедившись, что три ответа остаются пустыми.
Я знаю, что служба работает, потому что она была протестирована и дает правильный ответ в другом месте.
Вот соответствующий код:
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.info(this.geocodeResponse)
console.info(this.longitude)
console.info(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, но без запуска тегов в отладчике переменные остаются неназначенными.
Я могу предоставить дополнительный код и вывод журнала, если это необходимо. Уточните, пожалуйста, что необходимо для диагностики проблемы. Кроме того, хотя явное решение проблемы — это хорошо, мне бы очень хотелось понять, почему возникает эта проблема, потому что у меня есть несколько других компонентов, которые имеют аналогичные проблемы.
Возможный дубликат Как вернуть ответ на асинхронный вызов?





Проблема с компонентом в том, что он полагается на данные, которые ему сначала нужно получить от асинхронной операции. Есть 2 распространенных способа обойти это:
Вот некоторый код, который иллюстрирует вышеуказанные пункты. Не весь ваш код дублируется ниже.
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;
});
}
динамическая карта.component.html
<div *ngIf = "isInitialized">
<p>dependent html here</p>
</div>
См. также Как вернуть ответ на асинхронный вызов? для получения дополнительной информации об асинхронных вызовах в javascript.
Есть ли способ принудительно обновить решение (1)? Карта загружается с координатами по умолчанию, однако долгота и широта никогда не обновляются.
@Secaucus - вы могли бы, но я не знаю, как вы запускаете его для загрузки, это действительно зависит от API и от того, можете ли вы вызвать его из javascript. Я бы проверил их документацию. В качестве альтернативы просто используйте решение 2 и подождите, пока вы не получите ответ от API, прежде чем загружать html для этого элемента управления.
Это произошло потому, что
.subscribe— асинхронная функция.