Как использовать .catch в firebase onSnapshot - PullRequest
0 голосов
/ 14 апреля 2020

Я создал приложение для чата Ioni c Firebase. Проблема, которую я думаю, у меня заключается в том, что я настроил моментальный снимок запроса при инициализации страницы сообщения следующим образом:

  ngOnInit() {
      this.messageService.getAllMessages()
      .doc(`${this.userId[0] + '-' + this.userId[1]}`)
      .collection('message')
      .orderBy('createdAt', 'asc')
      .onSnapshot((doc) => {
        this.messages = [];
        doc.forEach((snap) => {
          this.messages.push({
            content: snap.data().content,
            createdAt: snap.data().createdAt,
            userId: snap.data().userId
          });
        });
        console.log('messages', this.messages);
      });
  }

Проблема заключается в том, что при первоначальной попытке отправить сообщение отсутствует сообщение, страница не загружается при первой попытке go.

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

ERROR Error: Uncaught (in promise): Error: No value accessor for form control with unspecified name attribute
Error: No value accessor for form control with unspecified name attribute
    at _throwError (vendor.js:70776)
    at setUpControl (vendor.js:70646)
    at NgModel._setUpStandalone (vendor.js:73693)
    at NgModel._setUpControl (vendor.js:73668)
    at NgModel.ngOnChanges (vendor.js:73604)
    at checkAndUpdateDirectiveInline (vendor.js:63813)
    at checkAndUpdateNodeInline (vendor.js:65493)
    at checkAndUpdateNode (vendor.js:65432)
    at debugCheckAndUpdateNode (vendor.js:66400)
    at debugCheckDirectivesFn (vendor.js:66343)
    at resolvePromise (polyfills.js:3193)
    at resolvePromise (polyfills.js:3150)
    at polyfills.js:3254
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (polyfills.js:2785)
    at Object.onInvokeTask (vendor.js:57358)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (polyfills.js:2784)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (polyfills.js:2557)
    at drainMicroTaskQueue (polyfills.js:2963)
defaultErrorLogger @ vendor.js:55398
handleError @ vendor.js:55450
next @ vendor.js:57952
schedulerFn @ vendor.js:52576
__tryOrUnsub @ vendor.js:133918
next @ vendor.js:133857
_next @ vendor.js:133804
next @ vendor.js:133781
next @ vendor.js:133566
emit @ vendor.js:52556
(anonymous) @ vendor.js:57389
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ polyfills.js:2753
push../node_modules/zone.js/dist/zone.js.Zone.run @ polyfills.js:2512
runOutsideAngular @ vendor.js:57315
onHandleError @ vendor.js:57389
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.handleError @ polyfills.js:2757
push../node_modules/zone.js/dist/zone.js.Zone.runGuarded @ polyfills.js:2526
_loop_1 @ polyfills.js:3056
api.microtaskDrainDone @ polyfills.js:3065
drainMicroTaskQueue @ polyfills.js:2970
Promise.then (async)
scheduleMicroTask @ polyfills.js:2946
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ polyfills.js:2775
onScheduleTask @ polyfills.js:2663
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ polyfills.js:2766
push../node_modules/zone.js/dist/zone.js.Zone.scheduleTask @ polyfills.js:2600
push../node_modules/zone.js/dist/zone.js.Zone.scheduleMicroTask @ polyfills.js:2620
scheduleResolveOrReject @ polyfills.js:3241
resolvePromise @ polyfills.js:3187
(anonymous) @ polyfills.js:3103
webpackJsonpCallback @ runtime.js:26
(anonymous) @ pages-messages-messages-module.js:1
vendor.js:116244 POST https://firestore.googleapis.com/google.firestore.v1.Firestore/Write/channe

Итак, мой вопрос, есть ли способ обработки нулевых возвращаемых значений в запросе .Snapshot в firebase?

Я пробовал это:

  ngOnInit() {
    try {
      this.messageService.getAllMessages()
      .doc(`${this.users[0] + '-' + this.users[1]}`)
      .collection('message')
      .orderBy('createdAt', 'asc')
      .onSnapshot((doc) => {
        this.messages = [];
        doc.forEach((snap) => {
          this.messages.push({
            content: snap.data().content,
            createdAt: snap.data().createdAt,
            userId: snap.data().userId
          });
        });
        console.log('messages', this.messages);
      });
    } catch (error) {
      console.log('Message page error', error);
    }
  }

1 Ответ

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

Запрос Firestore не завершается ошибкой, если не находит подходящих документов. Он просто предоставляет QuerySnapshot, который не содержит документов.

Переменная doc в вашем коде - это объект типа QuerySnapshot (так что это не «документ»). У него есть метод с именем empty () , который вы можете использовать, чтобы увидеть, не содержит ли он документов. Кроме того, вы можете проверить его свойство docs для нулевой длины.

.onSnapshot(querySnapshot => {
  if (!querySnapshot.empty()) {
    this.messages = [];
    querySnapshot.forEach((snap) => {
      this.messages.push({
        content: snap.data().content,
        createdAt: snap.data().createdAt,
        userId: snap.data().userId
      });
    });
  }
  else {
    // what do you want to do if there are no documents?
  }
});

На основе предложений я обновил свой код следующим образом и с той же проблемой:

ngOnInit() {
  this.messageService.getAllMessages()
    .doc(`${this.users[0] + '-' + this.users[1]}`)
    .collection('message')
    .orderBy('createdAt', 'asc')
    .onSnapshot((doc) => {
      if (!doc.empty) {
        this.messages = [];
        doc.forEach((snap) => {
          this.messages.push({
            content: snap.data().content,
            createdAt: snap.data().createdAt,
            userId: snap.data().userId
          });
        });
      } else {
        this.messages = [];
      }

      console.log('messages', this.messages);
    });
}
<ion-list lines="none" *ngIf="messages.length > 0">
  <ion-item *ngFor="let msg of messages; index as i; trackBy: trackByCreated">
    <div size="9" *ngIf="theirItinerary.userId === msg.userId" class="message other-user">
      <span>{{msg.content}}</span>
      <div class="time" text-right><br> {{msg.createdAt | date: 'short'}}</div>
    </div>
    <div offset="3" size="9" *ngIf="theirItinerary.userId !== msg.userId" class="message me" slot="end">
      <span>{{msg.content}}</span>
      <div class="time" text-right><br> {{msg.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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...