javascript - 我怎样才能正确地消除 firebase 云功能的执行

标签 javascript firebase google-cloud-functions debouncing

我有一个 Firebase 云函数,它根据 Firebase 的 documentation 中提供的示例监控对我的实时数据库的更改。 .

我的函数工作正常,并按照其编写的方式执行每次更改。

话虽如此,并且根据 Firebase 的建议:

• Debouncing - when listening to realtime changes in Cloud Firestore, this solution is likely to trigger multiple changes. If these changes trigger more events than you want, manually debounce the Cloud Firestore events.

我想这样做。

谁能提供一个好的方法?

如果我们根据 Firebase 的示例查看此函数:

exports.onUserStatusChanged = functions.database.ref('/status/{uid}').onUpdate(
            async (change, context) => {

  // Get the data written to Realtime Database
  const eventStatus = change.after.val();

  // Create a reference to the corresponding Firestore document
  const userStatusFirestoreRef = firestore.doc(`status/${context.params.uid}`);

  // re-read the current data and compare the timestamps.

  const statusSnapshot = await change.after.ref.once('value');
  const status = statusSnapshot.val();

  // If the current timestamp for this data is newer than
  // the data that triggered this event, we exit this function.

  if (status.last_changed > eventStatus.last_changed) {
    return null;
  }

  // Otherwise, we convert the last_changed field to a Date

  eventStatus.last_changed = new Date(eventStatus.last_changed);

  // write it to Firestore

  userStatusFirestoreRef.get().then((user: any) => {
    user.forEach((result: any) => {       
      result.ref.set(eventStatus, { merge: true })
    });
  });
  return;
});

我应该如何尝试去抖动它的执行?

我可以尝试去抖动 .onUpdate() 事件吗?

我最初认为以下内容就足够了:

functions.database.ref('/status/{uid}').onUpdate(
  debounce(async(change:any, context:any) => {
    ...
  }, 10000, {
    leading: true,
    trailing: false
  })
);

但是,感谢@doug-stevenson 指出,由于以下原因,尝试以这种方式消除 onUpdate 事件的抖动是行不通的:

“这是行不通的,因为函数的每次调用都可能发生在完全不同的没有共享上下文的服务器实例中。”

最佳答案

一种方法是使用任务调度程序(例如 Google Cloud Tasks)。您将使用任务调度程序来控制何时处理事件,而不是直接在云函数本身中处理事件。

我提供了两种方法:一种用于去抖,一种用于延迟 throttle 。

去抖动

这个想法是为每个云函数调用排队一个任务。如果已经为该实体安排了任务,则应取消现有任务。

例如,如果您的去抖间隔为 5 分钟,则将每个任务安排在未来 5 分钟后。安排好每个任务后,取消该实体的前一个任务(如果有的话)。当任务最终运行时,这意味着在 5 分钟内没有其他云调用(即成功去抖)。

延迟 throttle

延迟节流意味着您的事件在每个时间间隔最多处理一次,在时间间隔结束时。

想法是:每次云函数运行时,仅当任务不是重复时才将其入队。您需要想出一个任务命名约定,让您删除冗余任务。

例如,您可以将计划的执行时间附加到实体 ID。当您的云函数运行时,如果已经有针对该 ID 和时间的计划任务,您可以安全地忽略该事件。

这是一个每分钟最多处理一次事件的代码示例。

// round up to the nearest minute
const scheduleTimeUnixMinutes = Math.ceil(new Date().getTime() / 1000 / 60);
const taskName = id + scheduleTimeUnixMinutes.toString();
const taskPath = client.taskPath(project, location, queue, taskName);

// if there's already a task scheduled for the next minute, we have nothing
// to do.  Google's client library throws an error if the task does not exist.
try {
  await client.getTask({ name: taskPath });
  return;
} catch (e) {
  // NOT_FOUND === 5.  If the error code is anything else, bail.
  if (e.code !== 5) {
    throw e;
  }
}

// TODO: create task here

关于javascript - 我怎样才能正确地消除 firebase 云功能的执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58644361/

相关文章:

javascript - 使用 jQuery 获取 HTML 属性值

android - 当我嵌套两个值事件监听器时,它们是异步运行还是较低的等待较高的完成?

node.js - Firebase 提供 --only 功能,admin.auth() 在本地不起作用,除非我手动设置 key.json

firebase - Firestore 云功能接受多部分/表单数据?

javascript - EmberJS 嵌套 View 和 Controller

javascript - 在 Javascript 构造函数中引用实例变量

javascript - 将 div 捕捉到滚动时的固定导航栏

firebase - 存储 FCM token 的最佳方式是什么?

android - 基于 Firestore 角色的身份验证无法按预期工作

firebase - 在 Firebase Cloud 函数中获取请求 URL