在异步请求结束之前,Lambda函数不会返回

时间:2016-11-19 12:19:42

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

我想创建一个调用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
  • OS:Win 10

2 个答案:

答案 0 :(得分:3)

抱歉,您无法达到您想要的效果,至少不是这样。

当您使用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

答案 1 :(得分:0)

在您的处理程序中,您可以使用标志 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");
    };