javascript - 如何在 snapshot.foreach 中访问超出其范围的变量值

标签 javascript angular firebase firebase-realtime-database

return 语句在变量的 foreach 之外返回 null 值,我知道 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 给空值...

最佳答案

简单的回答是变量的范围不是问题。在 Javascript 中,var 的作用域为周围的函数。在提供的示例代码中,forEach 被传递给一个function,因此它的所有变量的作用域都如声明的那样。外部变量在内部函数中被捕获,因此它们的行为也正常。

问题在于,在 switchmap 返回值之前,内部 promise 未得到解析。

<小时/>

为了充分理解发生了什么,让我们看一下代码当前正在做什么以及它应该做什么。

为了论证,我将假设以下定义(即使我知道它们不正确):

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

这里,changeUserList 是一个字符串事件流,表示当前选定的UserIdselectedUserMessages 将是与当前所选用户关联的消息数组。

上面的代码简化后的意思如下:

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 调用在内部 promise 解析之前返回 this.chatMessages

<小时/>

switchmap 有一个有趣的功能:您可以从 switchmap 内部返回一个 promise ,并且它将等待该 promise 。这是 mix Promises and Observables 的一种方法.

从 switchmap 内部返回一个 promise 看起来像:

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
  }
<小时/>

话虽如此,对于 Firebase 来说,还有一种混合 Promise 和 Observables 的替代方案,称为 RxFire 。它是 Firebase 团队提供的一个相对较新的软件包,用于使用 RxJS Observables。由于您使用的是实时数据库,因此您需要look at these examples 。 List() 将发出子级更改流。您可以通过 map() 运算符pipe() 此流来执行其他处理(或提取 val() 并包含示例中的键)。您在 map() 中所做的操作与您在 forEach 中所做的操作类似。

AngularFirebase有一个在 FireStore 上使用 RxFire 的示例。

关于javascript - 如何在 snapshot.foreach 中访问超出其范围的变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52274249/

相关文章:

javascript - AngularJs:删除项目后取消选中复选框

javascript - 在 React 应用程序中使用 html-to-image 的问题

angular - 将 pdf URL 转换为 Base64

java - Firebase数据库如何从1个引用中获取一些值并等于2个引用来获取其键和值

javascript - Firestore/Rxfire - 查询集合然后订阅子可观察数组

android - Firebase 云消息传递的 AbstractMethodError

javascript - 如何避免重载 JavaScript CallStack?

javascript - Safari 上的 CSS 网格和绝对定位

javascript - 如何根据 id 分隔对象数组

来自父级的 Angular 访问路由参数