【问题标题】:Lambda Function does not return until async request endsLambda 函数在异步请求结束之前不会返回
【发布时间】:2017-04-03 05:34:43
【问题描述】:

我想做一个调用 API(第三方)并立即返回的函数,但它正在等待 API 响应。

这是代码示例:

var request = require('request');

// When I call functionOne it should trigger functionTwo and should end immediately, 
// but unfortunately, it is waiting for functionTwo to end
module.exports.functionOne = (event, context, cb) => {
    const uri = 'https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/functionTwo';
    request.post({ uri: uri });
    cb(null, "done functionOne");
};

module.exports.functionTwo = (event, context, cb) => {
    console.log("i'm functionTwo");
    setTimeout(function () {
        console.log("I'm functionTwo about to end");
        context.succeed("done functionTwo");
    }, 5000);
};

此外,如果我尝试调用context.succeed() 而不是cb(),它甚至会阻止 API 调用和函数立即返回而不调用 API。

我还在GitHub 上创建了一个问题。

附加信息:

  • 无服务器框架:v1.0.0-rc.2
  • 节点:v6.9.1
  • 操作系统:Win 10

【问题讨论】:

    标签: javascript node.js aws-lambda node-request serverless-framework


    【解决方案1】:

    抱歉,您无法实现您想要的,至少不能以这种方式。

    当您使用 request.post() 调用另一个函数时,您必须提供一个回调并且您必须等待它完成。

    你可以打电话给request.abort(),但这是一个老套的解决方案。

    module.exports.functionOne = (event, context, cb) => {
        const uri = 'https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/functionTwo';
        const r = request.post({ uri: uri }, (error, response, body) => {
            cb(error, "done functionOne");
        });
    
        r.abort();
        cb(null, 'forced abort on functionOne');
    };
    

    为什么这很hacky?因为你不能立即中止。您需要等待几毫秒才能在其他服务器中接收到请求,但是无法确切知道它何时发生。

    如果您知道第二个 Lambda 将运行 2 分钟,您可以添加一个 setTimeout 函数以在 5 秒后中止请求,并避免 functionOne 在空闲状态下长时间运行。但同样,这是一个糟糕的解决方案。

    为什么不将functionTwo 代码放在functionOne 中以避免启动第二个 Lambda?

    另一种解决方法是从 functionOne 调用 SNS 主题并将此主题配置为触发 functionTwo

    【讨论】:

    • FunctionTwo 在这里只是举例,在实际情况下,有一个第三方 api,我正在向该 api 发送带有一些数据的 post 请求,实际上它是 slack api
    • 好的,所以我建议您创建另一个特定于 Slack API 的问题。如果它是另一个 Lambda 函数,您可以使用 SNS,因为它只需几毫秒即可返回。如果 Slack 需要几秒钟才能完成,我不知道他们是否提供了另一种方式来排队请求而无需等待。
    • 否则,您可以中止请求以强制 Lambda 提前停止,但正如我所说,您需要等待片刻,Slack 才会收到请求。
    • 不幸的是,中止请求并没有解决我的问题
    【解决方案2】:

    在您的处理程序中,您可以使用标志callbackWaitsForEmptyEventLoop = false

        module.exports.functionOne = (event, context, cb) => {
        context.callbackWaitsForEmptyEventLoop = false
        const uri = 'https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/functionTwo';
        request.post({ uri: uri });
        cb(null, "done functionOne");
        };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 2018-09-11
      • 2017-10-25
      相关资源
      最近更新 更多