背景
据我所知,Firebase 触发的函数可以从一个触发事件运行多次(我想我可以从 Firebase 的日志中看到这一点)。
由于这可能是一种数据损坏行为,我想实现一些标志,如果发现该标志为 true
,该功能将允许该函数停止。
在数据库中创建该对象后,我希望此函数 (Typescript) 只运行一次。
例如:
adm.database().ref('/Users/{UserID}')
我计划在数据库中为每个用户节点存储一个键值对:
{"alreadyTriggered":true}
或者将'trigger'存储在一个单独的节点中,都没有关系。
然后当 Firebase 决定触发相应的函数时,我会检查并停止函数的执行,如果它不是第一次运行的话:
data = snapshot.val();
if (data.alreadyTriggered) {
return;
}
// The function continues here
实现
(部分括号可以省略,是在浏览器窗口写的伪代码-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 函数返回。您必须沿着 promise 链传播信息,以告知下一个回调是否执行其工作。
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
返回的 promise 的返回,这会导致您的函数超时。
请注意,使用 async/await 语法这一切都容易得多。
关于javascript - 如何停止执行 Firebase 触发的 Firebase 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59515529/