Что вызывает задержку между наблюдаемым результатом возврата и отображением результата в браузере?

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

Вот мой метод, чтобы получить профессионалов в свои услуги:

public getKeysFromGeoQuery(): Observable<any> {
    var keys = new Array();

    return Observable.create(observer => {
        this.geoQuery.on("key_entered", (key, location, distance) =>  {
            keys.push(key);                
            observer.next(keys);
        });

        this.geoQuery.on("key_exited", (key, location, distance) => {
            var index = keys.indexOf(key);
            if (index > -1) {
                keys.splice(index, 1);
            }              
            observer.next(keys);
        });
    });
}

Это мой тестовый компонент для использования сервиса:

import { Component } from '@angular/core';
import { LocationService } from '../../core/location.service';
import { Observable, Observer } from 'rxjs';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})
export class TestComponent {
  mapCenter = [34.021256, -118.403630];
  searchRadius = 4;

  result;
  error;
  time;

  constructor(private locationService: LocationService) {
    const startTime = Date.now();
    this.locationService.getGeoQuery({ center: this.mapCenter, radius: this.searchRadius });

    this.locationService.getKeysFromGeoQuery()
      .subscribe(keys => {
        this.result = keys;
        console.log("keys: ", this.result);
        this.time = Date.now() - startTime;
        console.log("time: ", this.time);
      });
  }
}

test.component.html:

<p>Result: {{result}} </p>
<p>Time: {{time}} </p>
<p>Error: {{error}} </p>

В моей консоли он показывает, что ключи извлекаются в течение 500 мс. Однако браузер показывает результат только через 3-4 секунды. Кто-нибудь знает, что вызывает эту задержку? Экран и консоль


person RedFour    schedule 06.01.2017    source источник


Ответы (1)


Похоже, что событие GeoFire on запускается за пределами зоны.

Вы можете проверить это, внедрив ChangeDetectorRef и явно активировав обнаружение изменений:

import { ChangeDetectorRef } from '@angular/core';
...
@Component({
  ...
})
export class TestComponent {
  ...
  constructor(
    private locationService: LocationService,
    private changeDetectorRef: ChangeDetectorRef
  ) {
    ...
    this.locationService.getKeysFromGeoQuery()
      .subscribe(keys => {
        this.result = keys;
        console.log("keys: ", this.result);
        this.time = Date.now() - startTime;
        console.log("time: ", this.time);
        this.changeDetectorRef.detectChanges();
      });
  }
}

Если событие запускается за пределами зоны, это может быть связано с тем, как сценарии Firebase и GeoFire включены в вашу сборку. Возможно, они загружаются до zone.js?

person cartant    schedule 06.01.2017
comment
Благодарю вас! Это отлично решило мою проблему. Похоже, мне нужно прочитать о zone.js - person RedFour; 06.01.2017
comment
Похоже, решение состоит в том, чтобы добавить this.changeDetectorRef.detectChanges(); ко всем моим пунктам subscribe и then. Когда вы говорите, что они загружаются до zone.js, есть ли способ это изменить? Нужно ли мне изменить мой package.json, чтобы зависимости были в другом порядке? - person RedFour; 06.01.2017
comment
Вам нужно будет предоставить все детали относительно вашего процесса сборки. Если бы я был в вашей ситуации, я бы поискал: инструменты, которые вы используете, Firebase, zone.js и т. д. - person cartant; 06.01.2017
comment
Как только вы разберетесь с заказами сценариев, вы сможете заставить его работать, поскольку у этого человека была противоположная проблема. Было бы утомительно разбрасывать ChangeDetectorRef повсюду. - person cartant; 06.01.2017
comment
Благодарю вас! Я вижу ту же проблему, используя Ionic 4. Я думал, что интеллектуальное/быстрое обнаружение изменений было одним из преимуществ Angular, но пока я не распаковал то, что делает zone.js, добавление changeDetectorRef.detectChanges() делает свое дело. - person briznad; 05.09.2018