Массив Angular 2 после подписки имеет элементы, но длина равна 0 - PullRequest
0 голосов
/ 25 августа 2018

Я использую Angular 2, и я заметил неожиданное поведение.

У меня есть класс источника данных, который расширяет DataSource, с двумя переменными:

private archives = new BehaviorSubject<MyArchive[]>([]);
public archives$: Observable<MyArchive[]> = this.archives.asObservable();
private filteredArchive: MyArchive[];

Я обновляю архивы таким образом в классе:

this.archives.next(this.filteredArchive);

В другом классе я пытаюсь подписаться на наблюдаемое, но это не работает:

ngAfterViewInit(): void {

    this.dataSource.archives$.subscribe((archive: Array<MyArchive>) => {

        console.log(archive.length);
        console.log(archive);
        console.log(archive.length);
    }
}

В журнале консоли выводится:

0
<THE ARCHIVE WITH AN OBJECT INSIDE AS IT SHOULD BE, WITH LENGTH = 1>
0

Так что я не могу перебрать архивную переменную, потому что ее длина равна 0. Что здесь происходит?

Ответы [ 4 ]

0 голосов
/ 26 августа 2018

Я решил проблему.Я забыл, что this.filteredArchive обновляется HTTP-запросом GET.Я пытался отправить данные в this.filteredArchive, используя forEach, но я забыл вызвать then (), когда все данные получены.Поэтому я пытался с помощью подписки получить доступ к результату, который еще не был готов.

Спасибо всем за ответы!

0 голосов
/ 26 августа 2018

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

export const reducer = () =>

   scan<MyArchive[]>((archive, update) => {
    //update your Archive or simply overwrite the value
    archive = update

    return archive

    }, []);

export class datasource {

   archives$ : Observable<MyArchive[]>;

   archives : Subject<MyArchive[]> = new Subject([]);

   update(newMyArchive: MyArchive[]) {
     this.archives.next(newMyArchive);
    }

   constructor(public http: HttpClient) {

   this.archives$ = this.archives.pipe(
     reducer(),
   //use the shareReplay so all your subscribers get the same values
     shareReplay(1)
     );
  this.archives$.subscribe();
}

, и вы можете обновить Arcjive, используя метод update в классе источника данных, например:

this.update(filteredArchive)
0 голосов
/ 26 августа 2018

При использовании этого оператора:

console.log(archive);

в консоли отображается ссылка на объект archive (см. документация MDN ).Содержимое объекта может отличаться, когда вы проверяете его в консоли (нажав на стрелку) по сравнению с тем, что было при выполнении оператора console.log.

Для того, чтобы увидеть, что является фактическим содержимымв определенный момент вы должны вывести строковое представление объекта:

console.log(archive.toString());
console.log(JSON.stringify(archive));

Вы можете поэкспериментировать с this stackblitz , чтобы увидеть различные выводы консоли.

0 голосов
/ 25 августа 2018

Я не уверен, почему вы создаете избыточно archives$ и archives. Вы можете сделать это только с одним объектом поведения.

Я думаю, вы должны сделать это:

// Create a BehaviorSubject for MyArchive[]
public archives$: BehaviorSubject<MyArchive[]> = new BehaviorSubject<MyArchive[]>([]);
// Create a private filtered Array for MyArchive.
private filteredArchive: MyArchive[];

А потом,

this.archives$.next(this.filteredArchive);
...