首页 > 解决方案 > 带有 Promise 的 Firestore 循环

问题描述

我无法弄清楚我如何在 Firebase 函数的循环内实现承诺有什么问题。将此函数作为 Firebase 计划函数运行时出现此错误:“TypeError: undefined is not a function”在我的 index.js 中指定第 202 行(如下)。该函数没有运行到完成(所有.thens 都没有完成)。我还有两个担忧:

  1. 我没有正确使用 Promise.all 并且没有在适当的地方返回承诺。

  2. 我在 Firebase 日志中收到此错误:“参数“documentPath”的值不是有效的资源路径。路径必须是非空字符串。” 尝试在下面代码的第 2 节中的路径中获取文档时。路径是正确的,并且确实是字符串,正如我通过检查参考对象所验证的那样。

      checkForTweetsToDelete: function(db) {
    
        ///////
        // 1. Get first collction - streamers
        let streamersRef = db.collection('streamers');
        let streamersQuery = streamersRef.get()
          .then(streamersSnap => {
    
            var promises = [];
    
            ///////
            // 2. Get settings for each streamer - Here is where I get a "Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string."
            streamersSnap.forEach(streamerDoc => {
    
              let tweetSettingsRef = db.collection('streamers').doc((streamerDoc.id.toString())).collection('TweetSettings').doc('Settings');
              let settingsDoc = tweetSettingsRef.get()
                .then(doc => {
    
                    ///////
                    // 3. Get all 'no' Tweets for this streamer
                    let tweetsRef = db.collection('streamers').doc(doc.data().twitchId).collection('TwitterPosts');
                    let tweetsQuery = tweetsRef.where('deleted', '==', 'no').get()
                      .then(tweetsSnap => {
    
                        var tweetPromises = [];
    
                        tweetsSnap.forEach(tweetDoc => {
    
                          /////////////
                          // 4. Delete Tweet
                          const client = new Twitter({
                            subdomain: "api", // "api" is the default (change for other subdomains)
                            version: "1.1", // version "1.1" is the default (change for other subdomains)
                            consumer_key: APP_KEY, // from Twitter.
                            consumer_secret: APP_SECRET, // from Twitter.
                            access_token_key: USER_TOKEN, // from your User (oauth_token)
                            access_token_secret: SECRET // from your User (oauth_token_secret)
                          });
    
                          const user = client.post('statuses/destroy', {
                            id: tweetDoc.id,
                            trim_user: 1
                          })
                          .then(twitterResponse => {
    
                            ///////
                            // 5. Write to DB that this has been deleted.
                            let tweetRef = tweetsRef.doc(tweetDoc.id.toString());
                            let updatedDoc = tweetRef.set({
                              deleted : 'yes'
                            }, {merge: true}).then(() => {
                              return;
                            });
    
                            return Promise.all([updatedDoc]);
                            // 5
                            ///////
    
                          });
                          // 4
                          /////////////
    
                          tweetPromises.push(user);
    
                        });
    
                        return Promise.all(tweetPromises);
                      });
    
                      return Promise.all([tweetsQuery]);
                      // 3
                      ///////
    
                });
    
                promises.push(settingsDoc);
            });
    
            return Promise.all(promises);
            // 2
            ///////
          });
    
        return Promise.all([streamersQuery]);
        // 1
        ///////
      }
    

还有我的 index.js

exports.scheduledFunction = functions.pubsub.schedule('every 1 minutes').onRun((context) => {
            console.log('This will run every 1 minutes!');

            var scheduled = require('./scheduledFunctions');
            if (admin.apps.length === 0 ) { admin.initializeApp(functions.config().firebase); }
            var db = admin.firestore();

            //scheduled.checkForTweetsToDelete(db);
            //return scheduled.checkForTweetsToDelete(db);
            return Promise.all( scheduled.checkForTweetsToDelete(db) ).then(function() { // Line 202
                console.log('Finished all promises!');
            });
        });

为了便于阅读,我删除了.thens 和 s 中的大部分逻辑。catch

编辑:

这个问题有助于理解这一切应该如何工作:Firebase (Angular) Promises with Loops in Loops并且在研究了它之后,我认为我正在按照解释进行操作,但仍然没有成功。

标签: javascriptfirebaseloopspromisegoogle-cloud-functions

解决方案


原来我在代码的其他地方调用了不正确的路径。我从数据库中获取了一个值,然后使用它来调用另一个引用路径,但该值未定义。修复后,我能够按照 Roamer-1888 的建议修复另一个承诺错误。


推荐阅读