Reputation: 619
Good day -- I've conducted many queries on this subject but can't find a good example that fits my situation.
Goal: To call multiple urls using request and async (these urls are different, some are xml and some are json), with the ability to scale the amount of links, with the end result of passing the data to the view for parsing.
Code:
var express = require('express');
var router = express.Router();
var request = require('request');
var parseString = require('xml2js').parseString;
var async = require('async');
var bis;
var url_bis = {
url: 'https://www.bis.org/list/cbspeeches/index.rss',
headers: {
'User-Agent': 'request'
}
};
function callback_bis(error, response, body) {
if (!error && response.statusCode == 200) {
bis = "";
parseString(body, function (err, result) {
bis = result;
bis = bis["rdf:RDF"]["item"];
});
}
}
var doj;
var url_doj = {
url: 'http://www.justice.gov/feeds/opa/justice-news.xml',
headers: {
'User-Agent': 'request'
}
};
function callback_doj (error, response, body) {
if (!error && response.statusCode == 200) {
doj = "";
parseString(body, function (err, result) {
_doj = result;
doj = _doj.rss.channel[0].item;
});
}
}
function feed_doj() {
request(url_doj, callback_doj);
}
function feed_bis() {
request(url_bis, callback_bis);
}
router.get('/', function(req, res, next) {
async.parallel({
bis: feed_bis,
doj: feed_doj
}, function(err, results) {
console.log(results)
// how to get the bis/doj response here in results?
});
});
module.exports = router;
Upvotes: 1
Views: 4185
Reputation: 3454
async needs to know when you've finished each task. To achieve this, the tasks are called with arguments which are callback functions. Your task functions, feed_doj
and feed_bis
, should call the callback functions. This is also the standard way of getting the output from the tasks - don't use global functions, it's widely considered bad form. Do this instead:
function feed_bis(callback) {
function callback_bis(error, response, body) {
if (!error && response.statusCode == 200) {
parseString(body, function (err, result) {
var bis = result["rdf:RDF"]["item"];
callback(null, bis);
});
}
}
request(url_bis, callback_bis);
}
// And same again for doj
Once the callback
functions have been called for both bis and doj, the main callback will be called with arguments (err, result)
; err
will be null
because you haven't done anything to handle error cases, and result
will be an object with properties named bis
and doj
.
Upvotes: 1
Reputation: 1085
You can accomplish this using the parallel method included in the async module,you just push all request in an array and then implement this: https://github.com/caolan/async/blob/master/README.md#parallel it is designed to execute a final callback when all processes end.
Upvotes: 0
Reputation: 9437
This is super-easy with promises and the Promise.all()
function:
var request = require('request-promise');
var calls = [
request({ url: 'http://...', headers: { ... } }),
request({ url: 'http://...', headers: { ... } }),
// ...as many more as you want...
];
Promise.all(calls).then(function(results) {
// do something with results[0]
// do something with results[1]
});
The Promise
API is native in newer versions of JS, and can be easily polyfilled in older JS engines, so it reduces the need for helper libs like async
.
This example runs all the requests in parallel. Promise.all()
waits for them all to finish, then gives you an array of results matching the original requests. Note also use of the request-promise
module, which just piggybacks on top of the request
module, but returns a promise instead of taking a callback.
Upvotes: 2