Могу ли я реализовать функцию чата с помощью облачных функций Firebase? - PullRequest
1 голос
/ 11 марта 2019

Я пытаюсь реализовать функциональность чата, используя Angular для внешнего интерфейса и функции Cloud с Cloud Firestore для внутреннего интерфейса. Frontend и Firestore общаются только через облачные функции. Вопрос, кстати, это хороший подход?

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

Количество чатов ограничено для двух пользователей, но пользователь может иметь много чатов с другими пользователями.

Мой код:

Облачные функции:

chatroomsEndpoint.js:

const chatroomsCollection = db.collection("chatrooms");

exports.getAllChatroomsByUserId = async function (req, res) {
    try {
        let chatrooms = [];
        // console.log(req.params.user_id);

        const resultA = await chatroomsCollection.where("userA", "==", req.params.user_id).get();
        resultA.docs.map(chatroom => {
            return chatrooms.push(chatroom.data());
        })

        const resultB = await chatroomsCollection.where("userB", "==", req.params.user_id).get();
        resultB.docs.map(chatroom => {
            return chatrooms.push(chatroom.data());
        })

        return res.status(200).send(chatrooms);
    }
    catch (error) {
        console.log('Error getting chatrooms', error);
        return res.send(false);
    }
};

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

Интерфейс (с угловым)

chat.service.ts:

constructor(
    private authService: AuthService,
    private http: HttpClient,
    private router: Router
  ) {
    this.headers.append('Content-Type', 'application/json');
  }

  getAllChatroomsByUserId() {
    return this.http.get(`${this.apiUrl2}/${this.authService.getUser().uid}`);
  }

Chatroom-list.component.ts:

userChats$;

  constructor(
    public authService: AuthService,
    public chatService: ChatService,
    public router: Router,
    public userStoreService: UserStoreService
  ) { }

  ngOnInit() {
    this.userChats$ = this.chatService.getAllChatroomsByUserId();
  }

Chatroom-list.component.html:

<ul>
    <li *ngFor="let chatroom of userChats$ | async">
      <a [routerLink]="'/' + chatroom.id">{{ chatroom.id }} - {{ chatroom.messages.length }} Messages </a>
    </li>
  </ul>

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

Я пытался придерживаться примера в видео https://www.youtube.com/watch?v=LKAXg2drQJQ&t=440s от Fireship, но в видео он делает это посредством прямой связи между Angular и Firestore. Я также восстановил это и мог заставить это работать. Также в этом примере используется snapshotChanges () - так я могу реализовать обновления в реальном времени?

Я уже искал все возможное, но не смог что-то найти.

Если понадобится что-то еще, я обновлю его.

1 Ответ

1 голос
/ 11 марта 2019

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

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

К сожалению, облачные функции не имеют такой же функциональности. Они не предназначены для того, чтобы «оставаться открытыми», как веб-розетки из Firestore. На самом деле, если вы попробуете это, они будут отключены через пару минут ... Даже если вы отрегулируете лимит времени ожидания, вы все равно столкнетесь с другими проблемами ... например, как вы будете обрабатывать сброшенные соединения ? ( Firestore websockets автоматически попытается повторно подключиться и заново открыть этот канал ). Какие пользователи что слушают? и т. д. Суть в том, что облачные функции должны быть короткими, «сделать это один раз», своего рода сервис… они не собираются «оставаться открытыми» и продолжать отправлять обновления клиенту старше 15+ минутное время.

Короче говоря, если вы хотите, чтобы браузер получал обновления в реальном времени от Firebase, тогда браузер должен подписаться непосредственно на эти события Firestore - без посредников облачной функции - как вы видите в видео.

EDIT:

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

...