как получить доступ к значению переменной вне ее области в snapshot.foreach - PullRequest
0 голосов
/ 11 сентября 2018

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

this.selectedUserMessages = this.changeUserList.switchMap(Userid => {
   if (Userid) {

    var self = this;
    this.loadingSerivice.isLoading.next(true);
    var ref = db.database.ref(`wfffsdf/usesdfdsfsrs/${Userid}/ress`);
    var i = 0;
    ref.once("value")
     .then(function(snapshot) {

      snapshot.forEach(function(childSnapshot) {
       var key = childSnapshot.key;
       // childData will be the actual contents of the child
       var invitedList = childSnapshot.val();
       self.invList.push({
        invitedid: invitedList
       });
       var invitedlistid = self.invList[i]['invitedid']['invitedBy'];
       //console.log(invitedlistid);
       if (invitedlistid == "asfsafafasfsafsafs") {
        //console.log("thread"+threadKey);
        self.ChatKey = key;
        //console.log(self.ChatKey+""+ db.database.ref(`1dfgsdfgdfhfdh/tdfsdfhsfhfhfdh/${key}/messages`)); 
       }
       i++;
      });
      self.chatMessages = self.getMessages(self.ChatKey);
      //  console.log(self.chatMessages);
     });
    return this.chatMessages;
   }
   return of(null);
  }

вернуть this.chatMessages дать нулевое значение ...

1 Ответ

0 голосов
/ 11 сентября 2018

Короткий ответ: объем переменных не является проблемой. В Javascript var ограничен окружающей функцией. В приведенном примере кода forEach передается function, поэтому все его переменные имеют область видимости, объявленную. Внешние переменные фиксируются во внутренней функции, поэтому они также ведут себя правильно.

Проблема в том, что внутренний promise не разрешается до того, как switchmap вернет значение.


Чтобы полностью понять, что происходит, давайте посмотрим, что в данный момент делает код и что он должен делать вместо этого.

Ради аргумента я собираюсь принять следующие определения (хотя я знаю, что они не верны):

selectedUserMessages : Observable<[]>;
      changeUserList : Observable<String>;

Здесь changeUserList - это поток строковых событий, представляющий текущий выбранный UserId. selectedUserMessages будет массивом сообщений, связанных с выбранным пользователем.

Код выше упрощен до следующего значения:

this.selectedUserMessages =
  // when changeUserList changes, switch selectedUserMessages to this new stream
  this.changeUserList.switchMap(Userid => {
    if (Userid) {

      // grab DB reference to user child list
      var ref = db.database.ref(`wfffsdf/usesdfdsfsrs/${Userid}/ress`);

      // CREATE A PROMISE TO QUERY THE DATABASE
      ref.once("value") // query once
        .then(function (snapshot) {
          snapshot.forEach(function (childSnapshot) {
            var key = childSnapshot.key;
            var val = childSnapshot.val();

            // process child
          });

          // store result
          this.chatMessages = this.getMessages(this.ChatKey);

        }); // END OF PROMISE

      // RETURN IMMEDIATELY, BEFORE PROMISE RESOLVES
      return this.chatMessages;
    }
    return of(null); // return null stream
  }

Проблема в том, что вызов switchmap возвращает this.chatMessages до разрешения внутреннего обещания.


switchmap имеет интересную особенность: вы можете вернуть обещание изнутри карты-переключателя, и оно будет ждать обещания. Это один из способов смешать Обещания и Observables .

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

this.selectedUserMessages =
  // when changeUserList changes, switch selectedUserMessages to this new stream
  this.changeUserList.switchMap(Userid => {
    if (Userid) {

      // grab DB reference to user child list
      let ref = db.database.ref(`wfffsdf/usesdfdsfsrs/${Userid}/ress`);

      // !!!! RETURN A PROMISE TO QUERY THE DATABASE !!!!
      return ref.once("value") // query once
        .then(function (snapshot) {

          let results = [];
          snapshot.forEach(function (childSnapshot) {
            let key = childSnapshot.key;
            let val = childSnapshot.val();
            // process child //
            results.push(/*processing results*/);
          });

          return results;

        }); // END OF PROMISE
    }
    else
      return of(null); // return null stream
  }

С учетом вышесказанного, существует альтернатива смешиванию Promises и Observables для Firebase под названием RxFire . Это относительно новый пакет от команды Firebase для использования RxJS Observables. Поскольку вы используете базу данных реального времени, вам нужно посмотреть на эти примеры . List () будет генерировать поток дочерних изменений. Вы можете pipe() этот поток через оператор map(), чтобы выполнить дополнительную обработку (или извлечь val () и включить ключ, как в примере). то, что вы делаете в map (), похоже на то, что вы делаете в forEach.

AngularFirebase содержит пример использования RxFire в FireStore.

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