获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

实时数据库触发器

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

借助 Cloud Functions,您无需更新客户端代码即可处理 Firebase 实时数据库中的事件。 Cloud Functions 允许您以完全管理权限运行实时数据库操作,并确保对实时数据库的每个更改都单独处理。您可以通过DataSnapshotAdmin SDK更改 Firebase 实时数据库。

在典型的生命周期中,Firebase 实时数据库函数执行以下操作:

  1. 等待对特定实时数据库位置的更改。
  2. 当事件发生并执行其任务时触发(有关用例示例,请参阅我可以使用 Cloud Functions 做什么? )。
  3. 接收一个数据对象,该对象包含存储在指定文档中的数据的快照。

触发实时数据库函数

使用 functions.database 为实时数据库事件创建新functions.database 。要控制函数何时触发,请指定事件处理程序之一,并指定它将侦听事件的实时数据库路径。

设置事件处理程序

函数让您可以在两个特定级别处理实时数据库事件;您可以专门监听创建、更新或删除事件,也可以监听路径的任何类型的更改。 Cloud Functions 支持实时数据库的这些事件处理程序:

  • onWrite() ,当在实时数据库中创建、更新或删除数据时触发。
  • onCreate() ,当在实时数据库中创建新数据时触发。
  • onUpdate() ,当实时数据库中的数据更新时触发。
  • onDelete() ,当数据从实时数据库中删除时触发。

指定实例和路径

要控制您的函数应在何时何地触发,请调用ref(path)以指定路径,并可选择使用instance('INSTANCE_NAME')指定实时数据库实例。如果您不指定实例,该函数将部署到 Firebase 项目的默认实时数据库实例例如:

  • 默认实时数据库实例: functions.database.ref('/foo/bar')
  • 名为“my-app-db-2”的实例: functions.database.instance('my-app-db-2').ref('/foo/bar')

这些方法指示您的函数处理实时数据库实例中特定路径的写入。路径规范匹配接触路径的所有写入,包括发生在其下方任何位置的写入。如果将函数的路径设置为/foo/bar ,它将匹配这两个位置的事件:

 /foo/bar
 /foo/bar/baz/really/deep/path

在任何一种情况下,Firebase 都会将事件解释为发生在/foo/bar ,并且事件数据包括/foo/bar中的旧数据和新数据。如果事件数据可能很大,请考虑在更深的路径中使用多个函数,而不是在数据库根附近使用单个函数。为获得最佳性能,请仅请求尽可能深层次的数据。

您可以通过用花括号将路径组件指定为通配符; ref('foo/{bar}')匹配/foo的任何孩子。这些通配符路径组件的值在函数的EventContext.params对象中可用。在此示例中,该值可用作context.params.bar

带有通配符的路径可以匹配来自单次写入的多个事件。插入的

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

匹配路径"/foo/{bar}"两次:一次与"hello": "world"匹配,另一次与"firebase": "functions"匹配。

处理事件数据

处理实时数据库事件时,返回的数据对象是DataSnapshot 。对于onWriteonUpdate事件,第一个参数是一个Change对象,它包含两个快照,分别表示触发事件前后的数据状态。对于onCreateonDelete事件,返回的数据对象是创建或删除的数据的快照。

在此示例中,该函数将指定路径的快照检索为snap ,将该位置的字符串转换为大写,并将修改后的字符串写入数据库:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();
      functions.logger.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return snapshot.ref.parent.child('uppercase').set(uppercase);
    });

访问用户认证信息

EventContext.authEventContext.authType ,您可以访问触发函数的用户的用户信息,包括权限。这对于执行安全规则很有用,允许您的函数根据用户的权限级别完成不同的操作:

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

exports.simpleDbFunction = functions.database.ref('/path')
    .onCreate((snap, context) => {
      if (context.authType === 'ADMIN') {
        // do something
      } else if (context.authType === 'USER') {
        console.log(snap.val(), 'written by', context.auth.uid);
      }
    });

此外,您还可以利用用户身份验证信息来“模拟”用户并代表用户执行写入操作。确保删除应用程序实例,如下所示,以防止并发问题:

exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snap, context) => {
      const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
      appOptions.databaseAuthVariableOverride = context.auth;
      const app = admin.initializeApp(appOptions, 'app');
      const uppercase = snap.val().toUpperCase();
      const ref = snap.ref.parent.child('uppercase');

      const deleteApp = () => app.delete().catch(() => null);

      return app.database().ref(ref).set(uppercase).then(res => {
        // Deleting the app is necessary for preventing concurrency leaks
        return deleteApp().then(() => res);
      }).catch(err => {
        return deleteApp().then(() => Promise.reject(err));
      });
    });

读取前一个值

Change对象有一个before属性,可让您检查在事件发生之前保存到实时数据库的内容。 before属性返回一个DataSnapshot ,其中所有方法(例如, val()exists() )都引用先前的值。您可以通过使用原始DataSnapshot或读取after属性再次读取新值。任何Change上的此属性是另一个DataSnapshot ,表示事件发生数据的状态。

例如, before属性可用于确保函数在首次创建时仅使用大写文本:

exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite((change, context) => {
      // Only edit data when it is first created.
      if (change.before.exists()) {
        return null;
      }
      // Exit when the data is deleted.
      if (!change.after.exists()) {
        return null;
      }
      // Grab the current value of what was written to the Realtime Database.
      const original = change.after.val();
      console.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return change.after.ref.parent.child('uppercase').set(uppercase);
    });