3

I want to make a function that calls an API (third party) and returns immediately, but it is waiting for API response.

Here is the code sample:

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);
};

Moreover, if i try to call context.succeed() instead of cb(), it even prevent API call and function return immediately without calling the API.

I have also created an issue on GitHub.

Additional info:

  • Serverless Framework: v1.0.0-rc.2
  • Node: v6.9.1
  • OS: Win 10
0

2 Answers 2

3

Sorry, but you can't achieve what you want, at least not in this way.

When you call another function using request.post(), you must provide a callback and you must wait for it to finish.

What you could do is to call request.abort(), but this is a hacky solution.

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');
};

Why is this hacky? Because you can't abort immediately. You need to wait a few milliseconds for the request to be received in the other server, but there is no way to know exactly when it happens.

If you know that the second Lambda will run for 2 minutes, you could add a setTimeout function to abort the request after 5 seconds and avoid having the functionOne running for a long time in a idle state. But again, this is a bad solution.

Why don't you place the functionTwo code inside functionOne to avoid starting a second Lambda?

Another workaround would be to call a SNS topic from functionOne and configure this topic to trigger functionTwo.

Sign up to request clarification or add additional context in comments.

4 Comments

FunctionTwo is here just for example, in actual case there is an api which is third party, and i'm sending post request to that api with some data, and actually it is slack api
Ok, so I suggest that you create another question specific to the Slack API. If it was another Lambda function, you could use SNS because it returns in just a few milliseconds. If Slack takes several seconds to complete, I don't know if they provide another way to queue the request without needing to wait.
Otherwise, you can abort the request to force Lambda to stop early, but as I said, you need to wait a few moments before Slack receives the request.
aborting request does not solved my problem unfortunately
0

In your handler you can use flag 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");
    };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.