Node.js - load data and then hit urls - async - javascript

I am new at node.js, so please be patient :)
What I need to do:
load from url Ids of users
Hit another url for every ID
What am I doing wrong?
var http = require('http');
var Client = require('node-rest-client').Client;
var client = new Client();
url = 'http://example.com/api/get-users';
client.get(url, function (data, response) {
if (data.status == 'OK') {
users = data.users;
users.forEach(function(item) {
newUrl = 'http://example.com/generateStats/' + item;
client.get(newUrl, function(data, response){
console.log(data);
});
});
}
});
The value of users is: [1,2,4,5,7,...]
Nothing in forEach is executing, why?

There is no status in data nor response so it never go inside the if block. To handle errors with node-rest-client, you have to listen to the error event:
var http = require('http');
var Client = require('node-rest-client').Client;
var client = new Client();
url = 'http://example.com/api/get-users';
client.get(url, function(data, response) {
// if there is an error, this function is not executed
var users = data.users;
users.forEach(function(item) {
newUrl = 'http://example.com/generateStats/' + item;
client.get(newUrl, function(data, response) {
console.log(data);
});
});
}).on('error', function(err) {
console.log('something is wrong: ' + err.code);
});
There is a response.statusCode though, it returns an http code like 200.

I think you need something like async
Check this answer: simplest-way-to-wait-some-asynchronous-tasks-complete-in-javascript

Related

Using request.on() for GET requests

When dealing with GET requests, should I be using request.on()?
For instance, in my main.js,
var http = require('http');
var dispatcher = require('./public/javascript/dispatcher.js');
var serverPort = 8124;
http.createServer(function (request, response) {
dispatcher.deal(request, response);
}).listen(serverPort);
and in dispatcher.js, I have
module.exports = {
deal: function(request, response) {
if(request.method === "GET") { // WITHIN THIS BLOCK
var get = require('./get.js');
// Pass data to the appropriate function
get.do(request, response);
} else if(request.method === "POST") {
var qs = require('querystring');
var requestBody = '';
request.on('data', function(data) {
requestBody += data;
});
request.on('end', function() {
var formData = qs.parse(requestBody);
var post = require('./post.js');
// Pass data to the appropriate function
post.doing(request, response, formData);
});
}
} // End deal
} // End exports
So to expand on my initial question and the code I've posted, the program works fine without the request.on(). My guess is that since there's no data to wait for from a GET request, there's no need for a require.on('end', ...). Any clarifications, recommendations, or suggestions are welcome!

Why doesn't my http request work for long JSON string?

var http = require('http');
var qhttp = require('q-io/http');
var formidable = require('formidable');
var categories;
qhttp.read("https://api.myjson.com/bins/509wa")
.then(function (json) {
categories = JSON.parse(json).categories;
})
.then(null, console.error);
module.exports.putCat = function(req, res){
var form = new formidable.IncomingForm();
form.parse(req, function(error, fields, files){
if(error){console.log(error)}
fields["catProd"] = [];
categories.push(fields);
var dataString = JSON.stringify({categories: categories});
console.log(dataString);
var options = {
host : "api.myjson.com",
path : "/bins/509wa.json",
method: "PUT",
headers: {"Content-Type": "application/json", "Content-Length": dataString.length}
};
function callback(response){
var body = "";
response.on('data', function(chunk){
body+=chunk;
});
response.on('end', function(){
console.log('Received data: '+body);
});
}
http.request(options, callback).write(dataString);
res.end();
});
};
screenshot
It works perfectly with something like JSON.stringify("hello":"world");. However, when I tried with my data that needs to be stored (which is much longer), it doesn't send anything to the API. Thanks in advance!
You have a race condition with the categories variable. If some external code calls putCat() quickly after loading the module, then the categories data may not be available yet.
If you have async module loading things to do, then you should probably expose a module constructor which returns a promise and you can then do the putCat() after that promise resolves.

With node.js how to I set a var to response from HTTP client?

I know this is probably Asynchronous Javascript 101 and I do have some books on the Kindle I could consult, but I am nowhere near my device.
I have a node app with a variable being assigned to a module that I'm loading. The module has one function that downloads a string of data from a URL.
The problem is, how do I not set the variable until the request has returned?
My code looks like this:
Downloader.js:
var http = require('http');
exports.downloadString = function(str) {
console.log("Downloading from " + str);
http.get(str, function(res) {
var data = [];
console.log("Got response: " + res.statusCode);
res.on('data', function (chunk) {
data.push(chunk);
});
res.on('end', function() {
return data.join('');
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
}
app.js:
var downloader = require('./lib/Downloader')
, dateParser = require('./lib/DateParser')
, eventIdGenerator = require('./lib/EventIdGenerator');
var report = downloader.downloadString("http://exampleapi.com");
console.log(report);
I need to wait until the variable named "report" is populated.
Obviously this means my Mocha tests are also failing as I'm still unsure of how to tell the test to wait until the variable is filled.
I'm sure this is extremely simple, but I am drawing a blank!
Thanks!
Node.js is (mostly) asynchronous, so you'd need to pass a callback function to your module:
Downloader.js:
var http = require('http');
exports.downloadString = function(str, callback) {
console.log("Downloading from " + str);
http.get(str, function(res) {
var data = [];
console.log("Got response: " + res.statusCode);
res.on('data', function (chunk) {
data.push(chunk);
});
res.on('end', function() {
callback(data.join(''));
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
};
app.js:
var downloader = require('./lib/Downloader')
, dateParser = require('./lib/DateParser')
, eventIdGenerator = require('./lib/EventIdGenerator');
downloader.downloadString("http://exampleapi.com", function(report) {
console.log(report);
});

Node.js http.get as a function

I am trying to make a function that returns the content of the webpage and this is what I have so far
var get_contents = function() {
var httpRequestParams =
{
host: "google.com",
port: 80,
path: "/?"
};
var req = http.get(httpRequestParams, function(res)
{
var data = '';
res.on('data', function(chunk) {
data += chunk.toString();
});
//console.log(data);
}).end();
return req;
}
This when I run this code, I see the html contents when the console logging is turned on but when I try to return the output, it just never works.
I can't figure out a way to return get_contents() anywhere. On the console, it just doesnt respond.
Thanks
Something like that: (dont forget to handle error and timeout)
var on_contents = function(cb) {
var httpRequestParams =
{
host: "google.com",
port: 80,
path: "/?"
};
var req = http.get(httpRequestParams, function(res)
{
var data = '';
res.on('data', function(chunk) {
data += chunk.toString();
});
res.on('end', function(){
cb(data);
});
//console.log(data);
}).end();
}
function onFinish(data) {
console.log(data);
}
on_contents(onFinish)
The short answer is: You can't return the data from that function. http.get is asynchronous, so it doesn't actually start running the callback until after your function ends. You'll need to have your get_contents function take a callback itself, check in the http.get handler whether you're done loading and, if you are, call the get_contents callback.
There is an awesome module [request][1] available in node.js.
var request = require('request'),
url = require('url');
var server = http.createServer(function (request, response) {
getPage("http://isohunt.com/torrents/?iht=-1&ihq=life+is+beautiful", function (body) {
console.log(body);
})
});
server.listen(3000);
More information can be found on http://www.catonmat.net/blog/nodejs-modules-request/

Nodejs output -Domain name not found

Technically this is my first try in nodejs and frankly I am not sure if I am doing it right. I am creating a local server that will stream the output from a distant server. However, when I run my code and I enter a URL in the browser, the program fails with the following message:
events.js:45
throw arguments[1]; // Unhandled 'error' event
^
Error: ENOTFOUND, Domain name not found
at IOWatcher.callback (dns.js:74:15)
The URL I used was: 127.0.0.1:9000/http://www.yahoo.fr. And in the browser I had the following message:
No data received
Unable to load the webpage because the server sent no data.
Here are some suggestions:
Reload this web page later.
Error 324 (net::ERR_EMPTY_RESPONSE): The server closed the connection without sending any data.
Any help is greatly appreciated.
Here is the code:
var base, dest, node_client,
count = 0,
url = require('url'),
util = require('util'),
http = require('http'),
http_client = require('http'),
request = require('request'),
events = require('events'),
httpProxy = require('./lib/node-http-proxy'),
data_emitter = new events.EventEmitter();
httpProxy.createServer(9000, 'localhost').listen(8000);
http.createServer(function (req, res) {
if(!count)
{
base = url.parse(req.url).pathname;
node_client = http_client.createClient(80, base);
count++;
} else {
dest = req.url.substr(1, req.url.length -1);
}
request = node_client.request("GET", dest, {"host": base});
request.addListener("response", function (response) {
var body = "";
response.addListener("data", function (data) {
body +=data;
});
response.addListener("end", function () {
var out = JSON.parse(body);
if(out.length > 0) {
data_emitter.emit("out", out);
}
});
});
// request.close();
var listener = data_emitter.addListener("data", function(out) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(JSON.stringify(out));
res.close();
});
}).listen(9000);
Wild guess : your browser automatically requests 127.0.0.1:9000/favicon.ico and your program then tries to resolve favicon.ico which obviously fails and makes your program crash before it can send any data for the real request.
Why such tangled code?
This is a scenario where it makes sense to avoid nested callbacks, and use named functions. If you refactor the code, then people are more likely to be help you.
Can you do console.log(out) in your listener callback? Let us know if Node.js has any response data to return.
Well, for any newbie like me in this area, here is how I solved it. It's not clean and can be implemented in better way. Feel free to change, give suggestions.
Code:
var url = require('url'),
http = require('http'),
request = require('request'),
httpProxy = require('./lib/node-http-proxy'),
des = '',
util = require('util'),
colors = require('colors'),
is_host = true;
httpProxy.createServer(9000, 'localhost').listen(8000);
var server = http.createServer(function (req, res) {
var pathname = '';
if(is_host) {
dest = req.url.substr(0, req.url.length -1);
pathname = dest;
is_host = false;
} else {
pathname = req.url.substr(0, req.url.length);
if(pathname.charAt(0) == "/") {
console.log('new request');
console.log(pathname);
pathname = dest + pathname;
}
}
console.log(pathname);
request.get({uri: pathname}, function (err, response, html) {
res.end(html);
});
console.log('fetched from ' + pathname);
});
server.listen(9000);

Categories

Resources