Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async module error with parallel API requests

I'm a begginer in node.js and now I'm trying to get some API's result. I'm using async module (https://github.com/caolan/async) to parallel the request so it can be optimized.

The problem is the code is returning an error that each time points to a different line (the "callback(err, data)" line) in a different API call

That's is the error:

if (called) throw new Error("Callback was already called.");
                          ^
Error: Callback was already called.

I'm using the following function to request the API:

function getData(s, apiURL, getURL, callback) {

    var ht;
    if (s == 1) {
        ht = https;
    } else {
        ht = http;
    }

    var options = {
        hostname : apiURL,
        path : getURL,
        method : 'GET'
    }

    var content = "";

    ht.get(options, function(res) {
        console.log("Got response: " + res.statusCode);

        res.on("data", function(chunk) {

            content += chunk;
            //console.log(content);
            callback(content);
       });

    }).on('error', function(e) {
        console.log("Error: " + e.message);
        console.log(e.stack);
    });
}

To illustrate, this is how I'm using the async module:

var sources = sources.split(',')

    async.parallel({
        flickr : function(callback) {
            if (sources[0] == 1) {
                getData(0, 'api.flickr.com',
                "/services/rest/?method=flickr.photos.search&format=json&nojsoncallback=1&api_key=" + config.flickr.appid + "&per_page=5&tags=" + tags,

                function(data) {
                    callback(null, data); //here that the error may point
                });

            } else { callback(); }
        },
        instagram : function(callback) {
            if (sources[1] == 1) {

                getData(1, 'api.instagram.com',
                "/v1/tags/" + tags.split(',')[0] + "/media/recent?client_id=" + config.instagram,
                function(data) {                        
                    callback(null, data); //here that the error may point

                });
            } else { callback(); }
        } 
    }, function(err, results) {             
            console.log(results);
        });

Hope you can help me, thanks!

like image 668
fnnrodrigo Avatar asked Mar 29 '13 23:03

fnnrodrigo


People also ask

Does async await run in parallel?

You can call multiple asynchronous functions without awaiting them. This will execute them in parallel. While doing so, save the returned promises in variables, and await them at some point either individually or using Promise.

How do you use async parallel?

The first argument to async. parallel() is a collection of the asynchronous functions to run (an array, object or other iterable). Each function is passed a callback(err, result) which it must call on completion with an error err (which can be null ) and an optional results value. The optional second argument to async.

How does node handle concurrent request?

Multiple clients make multiple requests to the NodeJS server. NodeJS receives these requests and places them into the EventQueue . NodeJS server has an internal component referred to as the EventLoop which is an infinite loop that receives requests and processes them. This EventLoop is single threaded.

How do I run two methods parallel in JavaScript?

This is not possible. Javascript can only work in a single thread and there is no way to actually have two functions running in parallel. You need to make one call and then the other.


1 Answers

You are calling the callback function inside the data event (see the docs), which is triggered every time a chunk of data is received, that means several times.

Async.parallel is expecting the callback to be executed only once for each task.

To ensure only one callback per task, put the callback on an end event, for example.

Also, the error event should execute the callback as well.

like image 193
garst Avatar answered Oct 28 '22 09:10

garst