【问题标题】:How to properly write cloud functions that automatically update firestore documents如何正确编写自动更新 Firestore 文档的云函数
【发布时间】:2022-01-15 20:58:02
【问题描述】:

我正在尝试编写一个 firebase 云函数,该函数在每次新用户创建帐户时运行一个简单的 while 循环。由于某种原因,更新功能只运行一次并停止。我使用的代码粘贴在下面

const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp();

const firestore = admin.firestore();
var data;
var counter = 0;


 exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
   data = snapshot.data();
   while (counter < 5) {
    setInterval(updateCounter(counter), 5000);
  }
  
 })

 async function updateCounter(counter){
  await firestore.collection('testCollection').doc(data['username']).update({
    counter: admin.firestore.FieldValue.increment(1)
  });
  counter++;
 }


【问题讨论】:

  • 为什么在循环中使用 setInterval?
  • 我希望“updateCounter”函数在设定的时间后运行 5 次

标签: node.js firebase google-cloud-firestore


【解决方案1】:

如果要求运行此函数 5 次,每 5 秒一次,这可以工作。

for (let i =0;i<5;i++){
  await updateCounter();
  await sleep (5000);
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

【讨论】:

    【解决方案2】:

    Cloud Functions 在到达函数的最后一个 } 时会停止运行您的代码,否则它将无限期地向您收费。

    如果您希望您的代码继续运行,您需要返回一个承诺,该承诺会在您的代码完成其工作(最多 9 分钟)时解决。

    exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
      data = snapshot.data();
      return Promise((resolve, reject) => {
        while (counter < 5) {
          setInterval(updateCounter(counter), 5000);
        }
        setInterval(() => {
          if (counter >= 5) {
            resolve()
          }
        }, 5000)
      })
    })
    

    请注意,代码中的 while (counter &lt; 5) 循环仍然不会按照您的预期执行,但至少现在该函数将继续运行片刻,并且计数器将递增。


    这可能就是你想要的:

    exports.onUserCreate = functions.firestore.document('testCollection/{docID}').onCreate(async(snapshot, context) =>{
      data = snapshot.data();
      return Promise((resolve, reject) => {
        setTimeout(updateCounter,  5000);
        setTimeout(updateCounter, 10000);
        setTimeout(updateCounter, 15000);
        setTimeout(updateCounter, 20000);
        setTimeout(updateCounter, 25000);
        setInterval(() => {
          if (counter >= 5) {
            resolve()
          }
        }, 5000)
      })
    })
    

    这会调用updateCounter 5 次,每次在上一次调用后 5 秒。有可能在调用 resolve 之前无法完成最终的数据库更新,因此我强烈建议您阅读 sync, async, and promises 上的文档并观看 Doug 出色的 promises and async behavior in Cloud Functions 系列,了解更多关于异步行为的信息。

    【讨论】:

      猜你喜欢
      • 2019-06-29
      • 1970-01-01
      • 2018-03-28
      • 2019-08-07
      • 1970-01-01
      • 2020-10-25
      • 2019-06-27
      • 2020-02-11
      • 1970-01-01
      相关资源
      最近更新 更多