Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using nodejs async and request module

I'm trying to use async and request module together but i don't understand how the callbacks get passed. My code is

var fetch = function(file, cb) {
    return request(file, cb);
};

async.map(['file1', 'file2', 'file3'], fetch, function(err, resp, body) {
    // is this function passed as an argument to _fetch_ 
    // or is it excecuted as a callback at the end of all the request?
    // if so how do i pass a callback to the _fetch_ function
    if(!err) console.log(body);
});

I'm trying to fetch 3 files in order and concatenate the results. My head is stuck in callbacks I tryed and the different combinations I could think of. Google wasn't much help.

like image 658
andrei Avatar asked Jun 16 '12 11:06

andrei


People also ask

What is the use of Request module in node JS?

The request module is used to make HTTP calls. It is the simplest way of making HTTP calls in node. js using this request module.

How do you perform asynchronous HTTP request?

Ajax is the traditional way to make an asynchronous HTTP request. Data can be sent using the HTTP POST method and received using the HTTP GET method. To make an HTTP call in Ajax, you need to initialize a new XMLHttpRequest() method, specify the URL endpoint and HTTP method (in this case GET).

How do I use async and await in node JS?

Async functions are available natively in Node and are denoted by the async keyword in their declaration. They always return a promise, even if you don't explicitly write them to do so. Also, the await keyword is only available inside async functions at the moment – it cannot be used in the global scope.

Why is it that using async functions with event handlers is problematic?

Using async functions with event handlers is problematic, because it can lead to an unhandled rejection in case of a thrown exception: const ee = new EventEmitter(); ee.


2 Answers

Request is asynchronous function, it does not return something, when its job is done, it calls back. From request examples, you should do something like:

var fetch = function(file,cb){
     request.get(file, function(err,response,body){
           if ( err){
                 cb(err);
           } else {
                 cb(null, body); // First param indicates error, null=> no error
           }
     });
}
async.map(["file1", "file2", "file3"], fetch, function(err, results){
    if ( err){
       // either file1, file2 or file3 has raised an error, so you should not use results and handle the error
    } else {
       // results[0] -> "file1" body
       // results[1] -> "file2" body
       // results[2] -> "file3" body
    }
});
like image 61
Mustafa Avatar answered Oct 01 '22 07:10

Mustafa


In your example, the fetch function will be called three times, once for each of the file names in the array passed as the first parameter to async.map. A second, callback parameter will also be passed into fetch, but that callback is provided by the async framework and you must call it when your fetch function has completed its work, providing its results to that callback as the second parameter. The callback you provide as the third parameter to async.map will be called when all three of the fetch calls have called the callback provided to them.

See https://github.com/caolan/async#map

So to answer your specific question in the code, the callback function you provide is executed as a callback at then end of all requests. If you need to pass a callback to fetch you'd do something like this:

async.map([['file1', 'file2', 'file3'], function(value, callback) {
    fetch(value, <your result processing callback goes here>);
}, ...
like image 35
JohnnyHK Avatar answered Sep 28 '22 07:09

JohnnyHK