Angular (2+) - получение задержки в интерполяции привязки данных - PullRequest
0 голосов
/ 23 мая 2018

Я создаю входные данные для поиска по местоположению с помощью API подсказок местоположения Google.Все работает нормально, и результаты возвращаются почти мгновенно, но у меня есть несколько проблем с отображением данных.

  • Предложения возвращаются из службы, но иногда может потребоваться несколько секунд, чтобыпоказать в представлении (вы можете увидеть задержку, так как результаты сразу отображаются в консоли, но потребуется некоторое время, чтобы изменить представление)
  • Иногда результаты, отображаемые в представлении, показывают последний набор результатов, а нетекущие результаты

Я написал базовую копию того, что я пытаюсь сделать на StackBlitz, https://google -location-suggestions.stackblitz.io , и до сих портакие же проблемы здесь.Я обновил его, чтобы иметь состояние загрузки, которое лучше показывает проблему.

Ссылка StackBlitz с редактором: https://stackblitz.com/edit/google-location-suggestions

Я также включил сюда видео, чтобы вы могли увидеть, что язначит: https://vimeo.com/271476965

Буду признателен всем, кто поможет, если узнает, почему это происходит.

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Проблема, предложенная @ibenjelloun (спасибо), заключалась в обнаружении изменений.

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

this.ngZone.run(() => {
    this.locationSuggestionsLoading = false;
    this.locationSuggestions = locations;
});
0 голосов
/ 23 мая 2018

«Задержка» связана с обнаружением изменений, если вы щелкнете документ после ввода поиска местоположения, angular получит событие и обновит DOM.

API карт загружается после угловой загрузки,что делает код карт работающим вне ngZone.Я понял это, читая этот пост .

Основное исправление (как вы уже упоминали ранее в своем ответе) - это использование ngZone.run для запуска кода в угловой зоне:

private suggestions$ = new BehaviorSubject([]);

public search(location: string): void {
    this.service.getPlacePredictions(
      {
        input: location,
        componentRestrictions: { country: 'uk' }
      },
      (predictions, status) => this._ngZone.run(() => this.suggestions$.next(predictions.map(p => p.description)))
    );
  }

Я также добавил несколько других улучшений:

Загрузка API API карт только один раз в конструктор, чтобы избежать уже загруженной ошибки (также, когда stackblitz приводит к загрузке службы несколько раз, поэтому я изменяю перезагрузкумеханизм на странице в левом нижнем меню):

constructor(private mapsAPILoader: MapsAPILoader) {
    this.mapsAPILoader.load().then(() => {
      this.service = new google.maps.places.AutocompleteService();
      console.log('Maps API loaded');
      this.mapsApiLoading$.next(false);
    });
  }

Вы можете создать желаемую наблюдаемую с помощью каналов rxjs:

this.locationSuggestions$ = this.locationForm.get('location').valueChanges.pipe(
        filter(location => location && location !== ''),
        switchMap(location =>
            this.appService.getLocationSuggestions(location)));

Таким образом, вы можете напрямую подписаться на свою наблюдаемую в шаблонеиспользуя async:

<ng-container *ngIf="locationSuggestions$ | async as suggestions; else loading">
{{ suggestions | json }}
</ng-container>
<ng-template #loading>
  loading...
</ng-template>

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

Вот новый стек с изменениями.

...