首页 > 解决方案 > 如何停止执行 Firebase 触发的 Firebase 函数?

问题描述

背景

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

由于这可能是一种数据损坏行为,我想实现一些标志,如果它发现标志是true.

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

例如:

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

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

{"alreadyTriggered":true}

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

然后当 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 函数?

标签: javascripttypescriptfirebasefirebase-realtime-databasegoogle-cloud-functions

解决方案


您的return语句没有从顶级函数返回。它只是从您传递给的 lambda 函数返回then()。您必须将信息沿着 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,这将导致您的函数超时。

请注意,使用 async/await 语法这一切都容易得多。


推荐阅读