Firebase的云功能多次调用

时间:2017-03-16 13:21:51

标签: firebase firebase-realtime-database google-cloud-functions

我正在尝试使用Firebase的云功能,以便将我的firebase-queue工作人员转移到云端功能。每当我在给定的ref创建一个新节点时,我添加了一个简单的函数来添加最后更新的时间戳。该函数如下所示:

var functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp(functions.config().firebase);

exports.setLastUpdatedTimestamp = functions.database.ref('/nodes/{nodeId}')
  .onWrite(event => {
    const original = event.data.val();
    console.log('Adding lastUpdatedTimestamp to node ', original.name);
    return event.data.ref.child('lastUpdatedAtFromFC').set(Date.now());
  });

我部署了这个云功能,并且只在我的应用中添加了一个节点。我转到Firebase Functions仪表板,看到该函数已被调用169次,我不明白为什么。当我查看日志时,我会看到日志,例如将函数附加到所有过去的节点。

是否onWrite的行为与child_added类似,并为所有现有实体运行该函数?

每次更改和部署该功能时,是否会重复此操作?

我期待它只为新添加的节点运行一次。

3 个答案:

答案 0 :(得分:9)

道格是对的。另外,最好知道如果你的函数卡在无限循环中,那么让它停止的方法是重新部署你的函数(使用firebase deploy)并修复循环,或删除该功能完全(通过从index.js删除并运行firebase deploy)。

答案 1 :(得分:7)

编写处理数据库写入的函数时,这是一个常见的错误。当你在一个位置处理初始写入的事件时,再做一次写回到同一个位置,第二次写入将触发另一个将再次运行该函数的事件,依此类推,这将是一个无限循环。

您的函数中需要一些逻辑来确定第二个写事件是否不应该重写到数据库。这将阻止循环。在您的情况下,您不需要函数来设置上次更新时间。您可以在客户端上使用特殊值来告诉服务器将当前时间插入字段。

https://firebase.google.com/docs/reference/js/firebase.database.ServerValue#.TIMESTAMP

答案 2 :(得分:0)

我遇到了这个确切的问题。这里有两个问题。一旦开始,如何停止无限循环。已经回答了。但是真正的问题是如何使用Firebase Cloud Function触发器向您的对象添加一个lastUpdated日期字段。

这是我尝试处理onWrite()循环问题。

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


exports.onWriteFeatherUpdateSummary = functions.database.ref('/messages/{id}')
    .onWrite((change, context) => {
      // Grab the current value of what was written to the Realtime Database.
      let updated = change.after.val();
      // Grab the previous value of what was written to the Realtime Database.
      const previous = change.before.val();
      let isChanged = true;
      let isCreated = (previous === null); // object 'created'

      // Only when the object gets updated
      if (!isCreated) {
        // An object should never directly change the lastUpdated value, this is for trhe trigger only
        isChanged = (updated.lastUpdated === previous.lastUpdated);
      }

      console.log(`isChanged: ${isChanged} ; isCreated: ${isCreated}`);

      if(isChanged) {
        // Insert whatever extra data you wnat on the update trigger
        const summary = `This is an update!`;

        // Add a 'createdDate' field on the first trigger
        if (isCreated) {
          // Make sure your object has a createdDate (Date) before the lastUpdated (Date)!
          Object.assign(updated,
              {
                createdDate : admin.database.ServerValue.TIMESTAMP
              }
            );
        }

        // Add lastUpdated Date field on very update trigger (but not when you just changed it with the trigger!)
        Object.assign(updated,
            {
              summary : summary,
              lastUpdated : admin.database.ServerValue.TIMESTAMP
            }
          );
      }

      return change.after.ref.set(updated);
    });