Alexander Mills
Alexander Mills

Reputation: 99960

Synchronizing request calls in Node

I am using the standard 'request' module

https://www.npmjs.org/package/request

I am wondering- if I have two successive/sequential request calls like so:

request.post({...});`  //first request

request.get({...});` //second request

...how to do I synchronize so that the first request always completes before the second gets called (the first request is authentication, so definitely needs to happen first).

The only way I know how to do this is to nest them like this:

 request.post({
    url: teamsnapURL,
    json: {
        user: "[email protected]",
        password: "******"
    }
}, function (err, res, body) {
    if (err) {
        throw err;
    }
    teamSnapToken = res.headers['x-teamsnap-token'];

    request.get({
        url: 'https://api.teamsnap.com/v2/teams',
        json: {
        },
        headers: {
            'x-teamsnap-token':teamSnapToken
        }
    }, function (err, res, body) {
        if (err) {
            throw err;
        }
        else{
            console.log('body:',body)
        }

})
});

is there another way?

One way is to use the node convention to pass in the callback function "next" and call that if authentication works, and otherwise throw an error. I will see if I can figure that out and add that as an answer (this questions doesn't have just one answer).

Here is non-nested callback way, solved with passing a function as a parameter. This appears to be pretty standard to avoided heavily nested function calls.

var request = require('request');
var teamsnapURL = 'https://api.teamsnap.com/v2/authentication/login';

var teamSnapToken = null;

var makeGetRequest = function(){

    request.get({
        url: 'https://api.teamsnap.com/v2/teams',
        json: {

        },
        headers: {
            'x-teamsnap-token':teamSnapToken
        }
    }, function (err, res, body) {
        if (err) {
            throw err;
        }
        else{
            console.log('body:',body)
        }

    });

};

var authPost = function(makeGetRequest){

    request.post({
        url: teamsnapURL,
        json: {

            user: "[email protected]",
            password: "*******"
        }
    }, function (err, res, body) {
        if (err) {
            throw err;
        }
        teamSnapToken = res.headers['x-teamsnap-token'];
        makeGetRequest();

})};

authPost(makeGetRequest);

although I have to say, this seems to be just a silly excuse to use functions as objects, because both functions are in the same file, so you could just call the other function by name without having it nested OR passed in as a parameter, whatevs.

Upvotes: 1

Views: 99

Answers (1)

Chris Tavares
Chris Tavares

Reputation: 30391

That's pretty much it - you way you know that a request has completed is that the callback fires, so if you have something that must happen after the first request completes, you have to do it in the callback.

There are ways to make this look easier, but it's still fundamentally the same thing. For example, using the async library, something like this:

async.waterfall([
    function (done) {
        request.post(firstRequest, function (err, res, body) { done(err, res, body); });
    },
    function (done, res, body) {
        teamSnapToken = res.headers[...];
        request.get(second-request, function (err, res, body) { done(err, res, body); });
    }
    ],
    function (err, result) {
        // final callback here
    });

Upvotes: 2

Related Questions