简体   繁体   中英

Express | Making multiple http requests asynchronously

I am currently building a small node application that makes a few api calls and renders a webpage with charts on it. I'm using express and jade as the render engine.

The problem is that I'm quite new to javascript and I don't know how to scheme out my http requests so I can pass an object of variables I got from the api (http get) when there is more than one request. I don't know how to map it out to make a single object and send it to the jade rendering engine.

Here is what I have so far :

app.get('/test', function(req, res) {
    apiRequestGoesHere(name, function(error, profile) {
        //Get some data here
    });
    anotherApiRequest(tvshow, function(error, list) {
        //Get some data here
    });
    res.render('test', data);
});

As it is right now, the page renders and the requests are not done yet, and if I place res.render inside one of the request, I can't access the other's data.

So what I want is a way to set it up so I can have multiple api calls, then make an object out of some elements of what is returned to me from the rest api and send it to Jade so I can use the data on the page.

You probably want to use async to help with this. async.parallel is a good choice for something simple like this:

app.get('/test', function(req, res) {
    async.parallel([
    function(next) {
        apiRequestGoesHere(name, function(error, profile) {
            //Get some data here
            next(null, firstData);
        });
    },
    function(next) {
        anotherApiRequest(tvshow, function(error, list) {
            //Get some data here
            next(null, secondData);
        });
    }], function(err, results) {
        // results is [firstData, secondData]
        res.render('test', ...);
    });
});

The first argument to those functions next should be an error if relevant (I put null ) - as soon as one is called with an error, the final function will be called with that same error and the rest of the callbacks will be ignored.

You can async parallel .

async.parallel([
    function(callback){
        // Make http requests
        // Invoke callback(err, result) after http request success or failure
    },
    function(callback){
        // Make http requests
        // Invoke callback(err, result) after http request success or failure
    }
],
// optional callback
function(err, results){
    // the results array will be array of result from the callback
});

The reason your page renders is the callbacks haven't "called back" yet. To do what you want, you would need to do something like:

app.get('/test', function(req, res) {
    apiRequestGoesHere(name, function(error, profile) {
        //Get some data here
        anotherApiRequest(tvshow, function(error, list) {
            //Get some data here
            res.render('test', data);
        });
    });
});

This strategy leads to what is known as "pyramid code" because your nested callback functions end up deeper and deeper.

I would also recommend the step library by Tim Caswell. It would make your code look something like:

var step = require('step');

app.get('/test', function(req, res) {
    step(
        function () {
            apiRequestGoesHere(name, this)
        },
        function (error, profile) {
            if error throw error;
            anotherApiRequest(tvshow, this)
        },
        function done(error, list) {
            if error throw error;
            res.render('test', list)
        }
    )
});

You could also use the group method to make the calls in parallel and still maintain the sequence of your callbacks.

Gl, Aaron

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM