Firebase 函数执行和订阅由 firebase 函数更新的列表

Posted

技术标签:

【中文标题】Firebase 函数执行和订阅由 firebase 函数更新的列表【英文标题】:Firebase function execution and subscription to list that is being updated by a firebase function 【发布时间】:2018-05-15 17:12:40 【问题描述】:

我认为firebase function 更新我在firebase database 中的列表正在被订阅该列表的subscription 捕获。从我的手机(在应用程序中)上的列表输出的样子......以及我的控制台输出的样子(它重复的方式),它似乎正在捕获整个列表并在每次添加时显示它。所以(我查了一下)...我相信这个等式代表正在发生的事情:

(N(N + 1))/2

这是你如何得到从 1 到 N 的所有数字的总和。在我的例子中做数学运算(N = 30 左右),我得到大约 465 个条目......所以你可以看到它正在加载吨,当我只希望它加载前 10 个时。

为了显示这里的输出发生了什么是一个pastebin https://pastebin.com/B7yitqvD。

在输出中,注意length - 1 load 上方/之前的数组。您可以看到它每次都快速返回一个包含更多条目的数组并将其添加到列表中。我也非常粗略地计算了我的列表中有多少项目,我得到了 440 ......所以与 465 的数字大致匹配。

事件链从不是具有此功能列表的页面的页面开始 - 它在firebase functions 端启动排序:

let a = this.http.get('https://us-central1-mane-4152c.cloudfunctions.net/sortDistance?text='+resp.coords.latitude+':'+resp.coords.longitude+':'+this.username);  
this.subscription6 = a.subscribe(res => 
console.log(res + "response from firesbase functions");
    loading.dismiss();
, err => 
    console.log(JSON.stringify(err))
    loading.dismiss();
)

这是页面上带有list 的函数,我认为它出于某种原因正在捕获整个排序。我相信订阅会以firebase function 的形式重复。

loadDistances() 
    //return new Promise((resolve, reject) => 
      let cacheKey = "distances"
      let arr = [];
      let mapped;
      console.log("IN LOADDISTANCES #$$$$$$$$$$$$$$$$$$$$$");


      console.log("IN geo get position #$$$$$$$5354554354$$$$$$$");

        this.distancelist = this.af.list('distances/' + this.username,  query: 
          orderByChild: 'distance',
          limitToFirst: 10
        );


        this.subscription6 = this.distancelist.subscribe(items => 
           let x = 0;

           console.log(JSON.stringify(items) + "      length - 1 load");



           items.forEach(item => 
             let storageRef = firebase.storage().ref().child('/settings/' + item.username + '/profilepicture.png');

              storageRef.getDownloadURL().then(url => 
                console.log(url + "in download url !!!!!!!!!!!!!!!!!!!!!!!!");
                item.picURL = url;
              ).catch((e) => 
                console.log("in caught url !!!!!!!$$$$$$$!!");
                item.picURL = 'assets/blankprof.png';
              );

             this.distances.push(item);

             if(x == items.length - 1) 
               this.startAtKey4 = items[x].distance;
             

             x++;
           )

           //this.subscription6.unsubscribe();
      )

  

只要我不从其他页面更新列表,loadDistances 中的 subscription 函数就可以正常工作 - 另一个指示它可能正在捕获整个排序并在排序时重复列出它。

我已经尽我所能地尝试了更新后列表中的unsubscribe...所以我可以在下次进入该列表的页面时加载 10 的列表,而不是在更新(一遍又一遍)。我知道firebase functionsbeta 中。这可能是他们这边的错误吗?这是我的firebase functions 代码:

exports.sortDistance = functions.https.onRequest((req, res) => 
  // Grab the text parameter.
    var array = req.query.text.split(':');
  // Push the new message into the Realtime Database using the Firebase Admin SDK.
  // Get a database reference to our posts
    var db = admin.database();
    var ref = db.ref("profiles/stylists");
    var promises = [];
    // Attach an asynchronous callback to read the data at our posts reference
    ref.on("value", function(snapshot) 
      //console.log(snapshot.val());
      var snap = snapshot.val();
      for(const user in snap) 
        promises.push(new Promise(function(resolve, reject) 
            var snapadd = snap[user].address;
            console.log(snapadd + " snap user address (((((((())))))))");
            if(snapadd != null || typeof snapadd != undefined) 
                    googleMapsClient.geocode(
                      address: snapadd
                    ).asPromise()
                        .then(response =>  
                          console.log(response.json.results[0].geometry.location.lat);


                          console.log("  +++   " + response.json.results[0].geometry.location.lat + ' ' + response.json.results[0].geometry.location.lng + ' ' + array[0] + ' ' + array[1]);


                          var distanceBetween = distance(response.json.results[0].geometry.location.lat, response.json.results[0].geometry.location.lng, array[0], array[1]);
                          console.log(distanceBetween + "      distance between spots");
                          var refList = db.ref("distances/"+array[2]);
                          console.log(snap[user].username + "    snap username");
                          refList.push( 
                            username: snap[user].username,
                            distance: Math.round(distanceBetween * 100) / 100
                          )

                          resolve();
                        )
                        .catch(err =>  console.log(err); resolve();)
            
            else 
                resolve();
               
        ).catch(err => console.log('error from catch   ' + err)));
        //console.log(typeof user + 'type of');

      

      var p = Promise.all(promises);
      console.log(JSON.stringify(p) +     "     promises logged");

      res.status(200).end();

    , function (errorObject) 
      console.log("The read failed: " + errorObject.code);
    );
);

奇怪的是,当我检查 firebase functions 日志时,所有这些似乎只运行一次......但我仍然认为订阅可能会在快速返回时以某种奇怪的方式捕获整个排序过程。为了尽可能清楚我认为正在发生的事情 - 我认为排序的每个阶段都被捕获在 (N(N + 1))/2...从 1 开始到大约 30...并且排序的总和结束最多是我列表的长度(一遍又一遍地重复 1-10 个项目)。

【问题讨论】:

虽然您在previous instance of this question 上指出它没有解决问题,但您仍然应该使用once() 而不是on() 这里:ref.on("value", function(snapshot) 我试过了......它让它看起来好像没有运行......我再试一次......并重新检查 firebase 函数日志,看看是否有任何东西被执行,而不仅仅是显示在我的应用中 当异步操作的数量变大时,就像在 Cloud Function sortDistance 中一样,很难正确链接所有 Promise。看起来您已经尝试过了,但有些遗漏了,例如这里:refList.push(...) 除了 ononce 之外,其他语法是否完全相同? 是的,用一次替换。 【参考方案1】:

我更新到angularfire2 5.0angular 5.0...花了一点时间,但最终解决了问题:

this.distanceList = this.af.list('/distances/' + this.username,
  ref => ref.orderByChild("distance").limitToFirst(50)).valueChanges();

在我的html 中,我使用了async 管道,它解决了排序问题:

...

<ion-item *ngFor="let z of (distanceList|async)" no-padding>

...

【讨论】:

以上是关于Firebase 函数执行和订阅由 firebase 函数更新的列表的主要内容,如果未能解决你的问题,请参考以下文章

使用firebase验证用户注册

在客户端检索由 firebase 分配的用户 ID 令牌时出错

Stripe 和 Firebase:FirebaseError:collection() 的第一个参数应为 CollectionReference、DocumentReference 或 Fireba

Firebase 函数:无法读取未定义的属性“user_id”

如何取消firebase的useEffect订阅

Uncaught FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - 在 vue.js 中调用 Fireba