Как разрешить Свойство подписки не существует в случае ошибки типа «число» в приложении Ioni c Angular? - PullRequest
0 голосов
/ 14 апреля 2020

Приведенный ниже код используется в руководстве Ioni c 5 / Angular для обновления объекта Place. Я пытаюсь применить этот же код к моему проекту, где я обновляю объект Conversation:

Сервис мест:

private _places = new BehaviorSubject<Place[]>([
    new Place(
      'p1',
      'Manhattan Mansion',
      'In the heart of New York City.',
      'https://lonelyplanetimages.imgix.net/mastheads/GettyImages-538096543_medium.jpg?sharp=10&vib=20&w=1200',
      149.99,
      new Date('2019-01-01'),
      new Date('2019-12-31'),
      'abc'
    )
  ]);

  get places() {
    return this._places.asObservable();
  }

updatePlace(placeId: string, title: string, description: string) {
    return this.places.pipe(
      take(1),
      delay(1000),
      tap(places => {
        const updatedPlaceIndex = places.findIndex(pl => pl.id === placeId);
        const updatedPlaces = [...places];
        const oldPlace = updatedPlaces[updatedPlaceIndex];
        updatedPlaces[updatedPlaceIndex] = new Place(
          oldPlace.id,
          title,
          description,
          oldPlace.imageUrl,
          oldPlace.price,
          oldPlace.availableFrom,
          oldPlace.availableTo,
          oldPlace.userId
        );
        this._places.next(updatedPlaces);
      })
    );
  }

А вот Place model:

export class Place {
  constructor(
    public id: string,
    public title: string,
    public description: string,
    public imageUrl: string,
    public price: number,
    public availableFrom: Date,
    public availableTo: Date,
    public userId: string
  ) {}
}

Как видите, на указанный выше метод updatePlace() можно подписаться при вызове.

Я пытаюсь создать метод addMessageToConversation(), который также может быть подписался, как и выше.

Вот мой код:

Служба разговоров:

private _conversations = new BehaviorSubject<Conversation[]>([
    new Conversation(
      'conversation1',
      'user3',
      'user1',
      [
        new Message('message1', 'Test message', 'user3', new Date(2018, 0O5, 0O5, 17, 23, 42, 11)),
        new Message('message2', 'Another message', 'user1', new Date(2018, 0O6, 0O5, 17, 23, 42, 11))
      ])
  ]);

  get conversations() {
    return this._conversations.asObservable();
  }

addMessageToConversation(conversationId: string, message: string) {
    this._conversations.getValue().find(conversation => conversation.id === conversationId)
      .messages.push(
        new Message(
          Math.random().toString(),
          message,
          this.authService.userId,
          new Date(Date.now())
        ));
  }

А вот Conversation & Message модели:

export class Conversation {
    constructor(
        public id: string,
        public userId: string,
        public mechanicId: string,
        public messages: Message[]
    ) { }
}

export class Message {
    constructor(
        public id: string,
        public text: string,
        public userId: string,
        public timestamp: Date
    ) { }
}

Приведенный выше код обновляет conversations, но я не могу подписаться на метод. Может кто-нибудь, пожалуйста, скажите мне, какие изменения мне нужно внести, чтобы это стало возможным?

Если я return, что в addMessageToConversation() и попытаться subscribe к нему, я получаю это сообщение об ошибке:

Свойство subscribe не существует для типа 'номер'

Кроме того, если я пытаюсь удалить _ из this._conversations.getValue().find(conversation => ..., я получаю эту ошибку сообщение:

Свойство 'getValue' не существует для типа 'Наблюдаемый'

1 Ответ

1 голос
/ 14 апреля 2020

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

import {switchMap} from 'rxjs/operators';
import {empty} from 'rxjs';

// Obs: notice we're returning a void observable (the empty() at the end),
//    to avoid returning an out-of-date value for the modified conversation.

addMessageToConversation(
  conversationId: string, 
  message: string
): Observable<Conversation> {
  return this._conversations.pipe(
      take(1),
      map((conversations) => conversations.find(c => c.id === conversationId)),
      tap((c: Conversation) => {
        // return case c or messages is falsey
        if(!c?.messages) {return;}

        c.messages.push(
          new Message(
            Math.random().toString(),
            message,
            this.authService.userId,
            new Date(Date.now())
          ));

        // Re-emit conversations array (with new reference)
        this._conversations.next(JSON.parse(JSON.stringify(this._conversations])));
      }),

      // This step is optional, just to avoid returning an out-of-date conversation
      switchMap((_oldConversation: Conversation) => empty())
  );
}

И вы можете использовать это так:

addMessageToConversation('conversation1', 'Hey, look! A new message')
  .subscribe();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...