【问题标题】:AWS Lambda: Async Calls outside handler (initialization section, invoke lambda)AWS Lambda:异步调用外部处理程序(初始化部分,调用 lambda)
【发布时间】:2019-08-09 05:06:27
【问题描述】:

我想通过以下代码在 lambda 处理程序之外调用一个异步函数:

var client;
(async () => {
    var result =  await initSecrets("MyWebApi");
    var secret = JSON.parse(result.Payload);
    client= new MyWebApiClient(secret.API_KEY, secret.API_SECRET); 
});

async function initSecrets(secretName) {
    var input = {
    "secretName" : secretName
    };
    var result = await lambda.invoke({
       FunctionName: 'getSecrets',
       InvocationType: "RequestResponse",
       Payload: JSON.stringify(input)
    }).promise();
    return result;
}

exports.handler = async function (event, context) {

    var myReq = await client('Request');
    console.log(myReq);
};

“客户端”未初始化。如果在处理程序中执行相同的代码,则可以完美运行。 initSecrets 包含 getSecrets() 的 lambda 调用,它调用 AWS SecretsManager 有谁知道如何在处理程序之外正确调用异步函数以进行初始化?

非常感谢您的支持。

【问题讨论】:

  • @Dennis Bauszus 在下面有正确的解决方案。您可以在 lambda 处理程序之外的部分中获得您的承诺,然后将其分配给一个新的局部变量并在其上“等待”。这样它只会被初始化一次,等待会确保它已经完成。

标签: asynchronous async-await aws-lambda initialization aws-secrets-manager


【解决方案1】:

client 在初始化之前被调用; client var 在 async 函数完成之前被“导出”(并调用)。当您调用await client() 时,客户端仍然是undefined

编辑,试试这样的方法

var client = async which => {
    var result =  await initSecrets("MyWebApi");
    var secret = JSON.parse(result.Payload);
    let api = new MyWebApiClient(secret.API_KEY, secret.API_SECRET); 
    return api(which) // assuming api class is returning a promise
}

async function initSecrets(secretName) {
    var input = {
    "secretName" : secretName
    };
    var result = await lambda.invoke({
       FunctionName: 'getSecrets',
       InvocationType: "RequestResponse",
       Payload: JSON.stringify(input)
    }).promise();
    return result;
}

exports.handler = async function (event, context) {

    var myReq = await client('Request');
    console.log(myReq);
};

【讨论】:

  • 非常感谢托宾的解释。那么,我怎样才能在模块构建时在处理程序之外初始化客户端呢?
【解决方案2】:

我在尝试让 next-js 与 aws-serverless-express 一起工作时遇到了类似的问题。

我通过执行以下操作来修复它(使用打字稿,所以只需忽略 :any type bits)

const appModule = require('./App');
let server: any = undefined;

appModule.then((expressApp: any) => {
  server = createServer(expressApp, null, binaryMimeTypes);
});

function waitForServer(event: any, context: any){
  setImmediate(() => {
    if(!server){
      waitForServer(event, context);
    }else{
      proxy(server, event, context);
    }
  });
}

exports.handler = (event: any, context: any) => {
  if(server){
    proxy(server, event, context);
  }else{
    waitForServer(event, context);
  }
}

所以对于您的代码,可能类似于

var client = undefined;

initSecrets("MyWebApi").then(result => {
    var secret = JSON.parse(result.Payload);
    client= new MyWebApiClient(secret.API_KEY, secret.API_SECRET)
})

function waitForClient(){
  setImmediate(() => {
    if(!client ){
      waitForClient();
    }else{
      client('Request')
    }
  });
}

exports.handler = async function (event, context) {
  if(client){
    client('Request')
  }else{
    waitForClient(event, context);
  }
};

【讨论】:

  • 非常感谢 Will 的提议。那应该可以。同时,我在全局上下文中添加了 var init = 0 来检测冷启动。
  • 没问题,检测冷启动与预热调用的有趣想法。
【解决方案3】:

这也可以通过 async/await 给 Node v8+ 解决

您可以像这样在模块中加载配置...

const fetch = require('node-fetch');

module.exports = async () => {

  const config = await fetch('https://cdn.jsdelivr.net/gh/GEOLYTIX/public/z2.json');

  return await config.json();

}

然后通过 require / 执行 config 模块在处理程序之外声明一个 _config。您的处理程序必须是异步函数。 _config 首先是一个承诺,您必须等待它才能解析为配置对象。

const _config = require('./config')();

module.exports = async (req, res) => {

  const config = await _config;

  res.send(config);

}

【讨论】:

    猜你喜欢
    • 2021-12-30
    • 2022-10-23
    • 2016-12-31
    • 2018-01-19
    • 2018-08-13
    • 2018-03-10
    • 1970-01-01
    • 2020-10-24
    • 2017-07-13
    相关资源
    最近更新 更多