如何停止执行 Firebase 触发的 Firebase 函数?



Background

据我所知,Firebase 触发的函数可以从一个触发事件中运行多次(我想我可以从 Firebase 中的日志中看到这一点(。

由于这可能是一种数据损坏行为,我想实现一些标志,如果发现该标志true,它允许函数停止。

在数据库中创建该对象后,我希望此函数(打字稿(仅运行一次。

例如:

adm.database().ref('/Users/{UserID}')

我计划在数据库中的每个用户节点存储一个键值对:

{"alreadyTriggered":true}

或者将"触发器"存储在单独的节点中,没关系。

然后,当Firebase决定触发相应的函数时,如果不是第一次运行该功能,我将进行检查并停止执行该功能:

data = snapshot.val();
if (data.alreadyTriggered) {
return;
}
// The function continues here

实现

(一些括号和括号可能丢失,它是在浏览器窗口中编写的 psecudocode-Typescript(

索引.ts:

import * as u from './users';
import * as ff from 'firebase-functions';
import * as adm from 'firebase-admin';
import * as types from './types';
// Triggered function
export const userCreated = ff.database.ref('/Users/{userId}').onCreate((sn, ctx) => {
let user: types.User = sn.val();
console.log(`New user created, User Id: ${ctx.params.userId}`);
return u.onCreated(user);
});

用户.ts:

// Function implementation
export function onCreated(user: types.User): Promise<void> {
return adm.database().ref("/Triggers").once('value', snapshot => {
let data: any = snapshot.val();
const alreadyTriggered: boolean = data.alreadyTriggered; 
}).then(alreadyTriggered => {
if (alreadyTriggered) {
// We would like to stop any execution here
return
}
else {
console.log(`Continuing processing`)
}
}).then(() => {
// This code should be reached only if alreadyTriggered is set to false
// do actual work with the user object
//...someNewData
//then save it
adm.database().ref('/Users').child(user.userId).update(someNewData)
})
}

问题

问题是我不知道如何可靠地停止执行该功能。我尝试使用return(不起作用(,break(仅用于循环(,并且我开始使用throw new Error('Stopping function execution'),但它似乎并没有可靠地停止 - 有时我在日志中看到该函数确实继续执行,尽管alreadyTriggered肯定是true

问题

如何从代码中停止执行 Firebase Typescript 函数?

您的return语句不是从顶级函数返回的。 它只是从您传递给then()的 lambda 函数返回。 您必须沿着承诺链传播信息,以告诉下一个回调是否执行其工作。

return adm.database().ref("/Triggers").once('value', snapshot => {
let data: any = snapshot.val();
const alreadyTriggered: boolean = data.alreadyTriggered; 
}).then(alreadyTriggered => {
if (alreadyTriggered) {
// We would like to stop any execution here
return false
}
else {
console.log(`Continuing processing`)
return true
}
}).then((continue) => {
// This code should be reached only if alreadyTriggered is set to false
// do actual work with the user object
//...someNewData
//then save it
if (continue) {
return adm.database().ref('/Users').child(user.userId).update(someNewData)
}
})

您还错过了上述update返回的承诺,这将导致您的函数超时。

请注意,使用 async/await 语法可以更轻松地完成此操作。

最新更新