Хобрук: Ваш путь к мастерству в программировании

Оператор SwitchMap с массивом

Я пытаюсь изучить rxjs и концепцию Observable в целом, и у меня есть сценарий, в котором у меня есть класс <Room>{}, где <Player>{} может присоединяться в стиле отношений «многие ко многим».

В Firestore у меня есть коллекция rooms, где у каждой комнаты есть свойство с именем players, которое представляет собой массив пользователей uids.

Когда создается компонент комнат, я подписываюсь на _roomService.getPlayersInRoom(roomId), который выглядит следующим образом:

getPlayersInRoom(roomId: string) {
  return this._db.doc<Room>(`rooms/${roomId}`).valueChanges().pipe(
    map(room => room.players),
    switchMap(players => players),//2
    switchMap(playerId => {
      if(playerId) {
        return this._db.doc<Player>(`users/${playerId}`).valueChanges();
      }
    })
  );
}

Я подпишусь на это позже с

.subscribe(player => {
    if (player) {
      this.players = new Array();
      this.players.push(player);
    }

Здесь есть пара проблем. Моя наблюдаемая не возвращает массив игроков, как ожидалось (см. Строку // 2, которая преобразует строку [] в строку)

Другая проблема заключается в том, что я обновляю массив this.players в своем компоненте каждый раз, когда эта комната изменяется (в противном случае .push() будет вставлять дубликаты.

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

15.04.2019

Ответы:


1

Во-первых, switchMap ожидает, что вы вернете Observable. Если это значение типа массива - оно превратит его в массив, используя from (см. Этот from пример ).

Если вы действительно хотите вернуть массив в поток - вы должны вернуть поток, например используя of: switchMap(value => of([]))

Тем не менее, в вашем случае вы хотите заменить каждый идентификатор в массиве потоком. Например, нам нужно будет использовать combineLatest оператор (название говорит само за себя). Каждый массив игроков мы будем переключать на новый поток. В этом новом потоке мы объединим последние значения valueChanges() потоков.

Вот пример:

getPlayersInRoom(roomId: string) {
    return this._db.doc<Room>(`rooms/${roomId}`).valueChanges().pipe(
      map(room => room.players),
      switchMap(players => {
        // turn array of player IDs
        // into array of streams of changes
        const playersStreams = players.map(
          playerId => this._db.doc<Player>(`users/${playerId}`).valueChanges()
        );

        // combine latest changes from all streams in that array
        return combineLatest(...playersStreams);
      })
    );
  }

Тогда в подписке players будет массив объединенных значений из valueChanges().

getPlayersInRoom(5)
  .subscribe(players => {
    this.players = players;
  })

Обратите внимание, что есть другие способы объединить значения из нескольких valueChanges(). Наиболее распространены: forkJoin и zip.

Есть и другие методы для отображения значения в потоке

Надеюсь это поможет

15.04.2019
  • Ты восхитителен! 15.04.2019
  • @ ska-dev, рад помочь :) 15.04.2019
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

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

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

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..