Не могу решить проблему с бесконечным циклом в приложении чата - PullRequest
0 голосов
/ 22 сентября 2019

Я создаю приложение чата ... при инициализации страницы чата я проверяю сообщения и сохраняю их в массиве сообщений

  ngOnInit() {
    this.messageService.getMessages().doc(`${this.sortItineraries[0] + '-' + this.sortItineraries[1]}`)
    .onSnapshot((doc) => {
      console.log('init message.page in snapshot', doc.data().message);
      this.messages = [];
      this.messages = doc.data();
      console.log('init message.page variable', this.messages);
    });
  }

Бесконечный цикл возникает, когда я отправляю сообщение со следующим кодом

  getMessages() {
    return this.allMessages;
  }

  getAllMessages() {
    return this.allMessages;
  }

  async createMessage(itineraries) {
    console.log('createMessage');
      const docRef = await firebase.firestore().doc(`messages/${itineraries}`).set({
      message: []
    });
  }

  async sendMessage(id, content, userId) {

    this.allMessages.doc(`${id}`)
    .onSnapshot((doc) => {
      if (doc.exists) {
        console.log('sendmessage doc exists');
        this.send(id, content, userId);
      } else {
        this.createMessage(id)
        .then(() => {
          console.log('sendmessage !doc exists');
          this.send(id, content, userId);
        });
      }
    });
  }

  async send(id, content, userId) {
    console.log('send');
    const uid = this.loggedInUser.uid;
    const ref = this.afs.collection('messages').doc(id);
    return ref.update({
      message: firebase.firestore.FieldValue.arrayUnion({
        content,
        createdAt: Date.now(),
        userId
      })
    });
  }
<ion-content>
  <ion-list lines="none">
    <ion-item *ngFor="let message of messages.message">
      <div size="9" *ngIf="myItinerary.userId !== message.userId" class="message other-user">
        <span>{{message.content}}</span>
        <div class="time" text-right><br>
        {{message.createdAt | date: 'short'}}</div>
        </div>

      <div offset="3" size="9" *ngIf="myItinerary.userId === message.userId" class="message me" slot="end">
        <span>{{message.content}}</span>
        <div class="time" text-right><br>
        {{message.createdAt | date: 'short'}}</div>
        </div>
    </ion-item>
  </ion-list>
</ion-content>

<ion-footer>
  <ion-toolbar light="light">
    <ion-row align-items-center no-padding>
      <ion-col size="8">
        <textarea autosize maxRows="3" [(ngModel)]="newMsg" class="message-input"></textarea>
      </ion-col>
      <ion-col size="3">
        <ion-button expand="block" fill="clear" color="primary" [disabled]="newMsg === ''" class="msg-btn"
        (click)="sendMessage()">
        <ion-icon name="ios-send" slot="icon-only"></ion-icon>
      </ion-button>
      </ion-col>
    </ion-row>
  </ion-toolbar>
</ion-footer>

Console Log

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

В службе я проверяю, создан ли документ

 async sendMessage(id, content, userId) {

    this.allMessages.doc(`${id}`)
    .onSnapshot((doc) => {
      if (doc.exists) {
        console.log('sendmessage doc exists');
        this.send(id, content, userId);
      } else {
        this.createMessage(id)
        .then(() => {
          console.log('sendmessage !doc exists');
          this.send(id, content, userId);
        });
      }
    });
  }

Если его не существует, я создаю его, прежде чем отправлять сообщения в массив сообщений в firebase

  async createMessage(itineraries) {
    console.log('createMessage');
      const docRef = await firebase.firestore().doc(`messages/${itineraries}`).set({
      message: []
    });
  }
  
    async send(id, content, userId) {
    console.log('send');
    const uid = this.loggedInUser.uid;
    const ref = this.afs.collection('messages').doc(id);
    return ref.update({
      message: firebase.firestore.FieldValue.arrayUnion({
        content,
        createdAt: Date.now(),
        userId
      })
    });
  }

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

  <ion-list lines="none">
    <ion-item *ngFor="let message of messages.message">

1 Ответ

2 голосов
/ 22 сентября 2019

Я полагаю, что ваша проблема связана с одним из следующих типов поведения:

  1. Когда для messages.message назначено новое значение, оно может быть равно json, но все же все объекты имеют новые указатели
  2. Следовательно, ngFor считает, что он получил новый массив различных объектов
  3. Следовательно, ngFor уничтожает старые элементы-ионы и снова их вводит для «новых» объектов, эффективно вызывая ngOnInit в каждом из них

Решением этой проблемы является добавление trackBy к ngFor (подробнее здесь https://angular.io/api/common/NgForOf)

Другое возможное поведение: некоторые из используемых вами методов возвращают бесконечный Observable, решение этой проблемы - добавление операторов сВозьмите (1) или фильтр (someFilterFunc) к вашему каналу (подробнее читайте здесь https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...