【问题标题】:Node.js 12.x AWS lambda does not return using firebase-admin realtime databaseNode.js 12.x AWS lambda 不使用 firebase-admin 实时数据库返回
【发布时间】:2021-07-24 18:47:38
【问题描述】:

我在这个问题上被困了几天,几乎没有进展,如果可以的话,请帮忙!

我有一个 Node.js (v12) AWS Lambda,它需要从我的 Firebase 实时数据库中提取数据,并将每条记录处理到 Redis 缓存中(如果它尚不存在)。该函数启动但从未完成,而是从 AWS 收到 Task timed out after 180.10 seconds

我尝试过的事情:

  • 使用exports.handler = async function(event) exports.handler = function(event, context, callback);
  • 对于上面的同步尝试,我尝试使用context.callbackWaitsForEmptyEventLoop = false 不;
  • 使用 promises 级联函数 将一堆 .then() 拼接在一起;
  • firebase-admin https 模块与 Firebase REST API 结合使用;
  • 稍后使用settimeout 触发回调对比不;
  • GOOGLE_APPLICATION_CREDENTIALS 环境变量设置为我的服务帐户凭据直接在代码中引用文件;
  • 我什至将 Lambda 本身的内存和超时时间增加到了它可以达到的最大值,并将我想从 Firebase 提取的数据减少到只有 1 条记录。

根据上述尝试,我得到的回应:

  • AWS(最频繁):Task timed out after 180.10 seconds
  • AWS(.then拼接方式):Function completed successfully(但没有实际处理数据);
  • 节点 HTTPS(REST API 方法):ETIMEDOUTECONNREFUSED

下面是我的目标,但仍然没有运气。我已经删除了缓存代码,因为我知道它可以正常工作。你看到的settimeout 是我到达这里之前的最后手段。

const admin = require("firebase-admin");
admin.initializeApp({
    credential: admin.credential.applicationDefault(),
    databaseURL: "https://{projectName}.firebaseio.com"
});
var result = [];
exports.handler = (event, context, callback) => {
    context.callbackWaitsForEmptyEventLoop = false;
    try {
        admin.database().ref("data").orderByChild("timestamp").limitToLast(1).once("value", snapshot => {
            if (snapshot.exists()) {
                console.log('snapshot exists...');
                let posts = snapshot.val();
                result = Object.keys(posts);
            }
            setTimeout(() => {
                admin.database().goOffline();
                admin.app().delete();
                callback(null, `Success! ${JSON.stringify(result)}`); // <-- NEVER RETURNS
            }, 2000);
        }, error => { 
            setTimeout(() => {
                admin.database().goOffline();
                admin.app().delete();
                callback(error); // <-- NEVER RETURNS
            }, 2000);
        });
    } catch (error) {
        setTimeout(() => {
            admin.database().goOffline();
            admin.app().delete();
            callback(error); // <-- NEVER RETURNS
        }, 2000);
    }
};

【问题讨论】:

    标签: javascript node.js firebase-realtime-database aws-lambda firebase-admin


    【解决方案1】:

    您似乎没有在函数的根级别存储或使用 setTimeout。您应该存储它,以便回调函数可以继续运行,因为它只存在于范围内。这样做还需要您绑定对象,以便在您决定将其推入数组以进行多个回调时拥有自引用

    var result = [];
    var timeOut;
    //...
    timeOut = setTimeout(() => {
                admin.database().goOffline();
                admin.app().delete();
                callback(error);
            }.bind(this), 2000);
    

    来源:MSDN Function.prototype.bind()

    如果 Binding 不是解决方案并且您想要一个阻塞方法,您可能对延迟函数感兴趣,它的行为与 setTimeout 相同,但适用于 Promise

    function sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    // Async function solution
    await sleep(2000);
      console.log('Two seconds later, showing sleep in a loop...');
    
    // non-Async solution
    sleep(2000)
    .then(()=> {
                admin.database().goOffline();
                admin.app().delete();
                callback(error);
            })
    .catch(e => console.log(e));
    

    【讨论】:

    • 感谢您的回复 DIGI Byte,绑定功能似乎无法设置在您上面放置的位置 - 我收到一个错误:',' expected.。有没有更好的方法来实现你提到的绑定?
    • 对于其他和全面的答案,我建议stackoverflow.com/a/2130411/2301161 和其他答案stackoverflow.com/a/8800171/2301161 - 如果其中任何一个有效,请告诉我
    • 另一种方法是使函数与延迟函数异步 - 添加了承诺延迟的代码
    • 不幸的是,我仍然收到超时错误 DIGI Byte - 你认为有更好的方法来实现相同的目标吗?
    • 是否有可能被 cors 策略阻止或配置错误?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2020-11-20
    • 1970-01-01
    • 2021-03-21
    • 2021-05-23
    • 1970-01-01
    相关资源
    最近更新 更多