Okay the question is when I "instanciate" a new object, and run a function from the object, it run 2 times, why's that ? Could some one explain me ?
Example:
server.js
var http = require("http");
var testObj = require("/path/to/obj");
exports.start = function() {
function onRequest(request, response)
{
var app = new testObj();
app.date();
response.writeHead(200, {"Content-Type": "application/json"});
response.write('Testing stuff!');
response.end();
}
http.createServer(onRequest).listen(config.core.server_port);
console.log("Server has started.");
};
obj.js
function Session(){
}
Session.prototype.date = function(){
var date = new Date();
console.log(date);
};
module.exports = Session;
The output in console should be only a date print, but I'm getting two dates prints, why is that?
Most likely the browser is making another request for favicon.
Related
Im a newbie with node.js and i'm trying to output some data to html.
My code works when I use console.log but not when I use response.end.
When I use response.end I only see on record while when I use console.log I get to see all the records
See my full code below:
var http = require('http');
var formOutput;
var WooCommerceAPI = require('woocommerce-api');
// Initialize the WooCommerceAPI class
var WooCommerce = new WooCommerceAPI({
//url: 'http://example.com', // Your store url (required)
});
function handleRequest(response) {
// GET example
WooCommerce.get('products', function (err, data, res) {
//console.log(res);
//var fs = require('fs');
//var jsonContent = JSON.parse(JSON.stringify(res, null, 4))
var jsonContent = JSON.parse(res)
for (var i = 0; i < jsonContent["products"].length; i++) {
var name = jsonContent["products"][i];
// this works well and I can output all records
//console.log(name['title']);
//console.log(name['id']);
//console.log(name['sku']);
//console.log(name['regular_price']);
//response.writeHead(200, { 'Content-Type': 'text/html' });
//res.end(name['id']);
formOutput = name['regular_price'];
//formOutput = '<h1>XYZ Repository Commit Monitor</h1>';
//response.write();
//Only get one record
response.end(formOutput);
//response.write('<html><head></head><body>');
//response.end("test");
//response.end('</body></html>');
}
});
//response.end(formOutput);
}
http.createServer(function (req, response) {
if (response.url === '/favicon.ico') {
response.writeHead(404);
response.end();
} else {
response.writeHead(200, { 'Content-Type': 'text/html' });
}
//code here...
handleRequest(response);
// response.end(formOutput);
}).listen(1337, "localhost");
console.log("Server running at http://localhost:1337/");
With Express, response.end() closes the communication channel after one call so only one element will be sent to the user. Don't use end() to send data, in your case, use response.json() (or send()) ONCE after you built the data array.
var dataToSend = [];
for (var i = 0; i < jsonContent["products"].length; i++) {
// build an array of data to send here
}
response.json(dataToSend);
On a side note, don't use response.end() unless you want to end the communication explicitly. response.json() and response.send() already close the channel when needed.
I have been trying to figure the following for the last couple of days and just can't seem to figure out the answer. I am new to node and JS (only experience is online tutorials).
I am trying to create a class (function) to scrape the source code from websites. I want to read in a url from the command line and return the html content. However, I seem to be getting different results when running the code different ways (which I think I should be getting the same results).
I have been reading about events in node and so I have used them a little in the code. One listener event prompts the me for the url and then after setting the url it (the listener function) emits a message, which is picked up by another listener which goes out and fetches the html content.
The problem I am having is that when I create an instance of the object, it seems like the request portion of the code does not execute. However, if I call the method from the instance I get the print out of the html content of the page.
Any help is appreciated. Thanks.
function test() {
var events = require('events').EventEmitter;
var request = require('request');
var util = require('util');
var that = this;
that.eventEmitter = new events();
that.url = 'http://www.imdb.com/';
that.eventEmitter.on('setURL',that.setUrl = function(){
console.log("Input the URL: ");
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (text) {
that.url = util.inspect(text);
that.url = that.url.substr(1, that.url.length - 4);
that.eventEmitter.emit('Get url html');
process.exit();
});
});
that.eventEmitter.on('Get url html',that.httpGet = function() {
console.log("Fetching... " + that.url);
request(that.url, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // Show the HTML for the Google homepage.
} else {
console.log("Error Encountered");
}
});
});
that.eventEmitter.emit('setURL');
}
var scrapper = new test(); //This asks me for the url and then only executes to first line of that.httpGet.
scrapper.httpGet(); // This gives the desired results from that.httpGet
I solved using the Prompt library https://www.npmjs.com/package/prompt
function test() {
var events = require('events').EventEmitter;
var prompt = require('prompt');
var request = require('request');
var util = require('util');
var that = this;
that.eventEmitter = new events();
that.url = 'http://www.imdb.com/';
that.eventEmitter.on('setURL',that.setUrl = function(){
prompt.start();
process.stdin.setEncoding('utf8');
prompt.get(['url'], function( err, result ) {
that.url = result.url;
that.eventEmitter.emit('Get url html');
} );
});
that.eventEmitter.on('Get url html',that.httpGet = function() {
console.log("Fetching... " + that.url);
request(that.url, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body); // Show the HTML for the Google homepage.
} else {
console.log("Error Encountered");
}
});
});
that.eventEmitter.emit('setURL');
}
var scrapper = new test(); //This asks me for the url and then only executes to first line of that.httpGet.
// scrapper.httpGet(); // This gives the desired results from that.httpGet
I ran the script from the commandline, input http://www.google.com and it retrieved the results without the additional call to scrapper.httpGet();
I 've been well with node.js until RxJS implementation.
Here is my trial code studying-
Reactive-Extensions / rxjs-node
https://github.com/Reactive-Extensions/rxjs-node
rx_http.js
(RxJS wrapper of the http lib of node.js)
var Rx = require("./rx.min");
var http = require("http");
for(var k in http)
{
exports[k] = http[k];
}
exports.createServer = function ()
{
var subject = new Rx.AsyncSubject();
var observable = subject.asObservable();
observable.server = http.createServer(function (request, response)
{
subject.onNext({ request:request, response:response });
subject.onCompleted();
});
return observable;
};
server.js
var http = require('./rx_http');
// rxServer
var serverObservable = http.createServer();
var port = 3000;
serverObservable.server.listen(port);
console.log("Server listening on port: "+port);
// HTTP request event loop function
serverObservable.subscribe(function (data)
{
var req = data.request;
console.log(req.headers);
var res = data.response;
res.writeHead(200, {'Content-Type':"text/html"});
res.end("hello world");
console.log("res content out");
});
// exceptiopn
process.on('uncaughtException', function (err)
{
console.log(['Caught exception:', err.message].join(" "));
});
The code ends up with one-time 'hello world' output to browser, and the RxServer stops reacting to another access (brwoser reload etc.).
I'm on the way to learn RxJS thing, but few documentation found on the web.
Tell me what's wrong with the code, and if you know better implementations, please share.
Thank you.
Use Rx.Subject instead of Rx.AsyncSubject in rx_http.js.
AsyncSubject caches the last value of onNext() and propagates it to the all observers when completed. AsyncSubject
exports.createServer = function ()
{
var subject = new Rx.Subject();
var observable = subject.asObservable();
observable.server = http.createServer(function (request, response)
{
subject.onNext({ request:request, response:response });
});
return observable;
};
Calling oncompleted on the subject when the first request arrives ends the observable sequence. Could you please remove that line an try again.
I hope it helps.
Ahmet Ali Akkas
i did this tutorial node.js eventEmitter, it worked nicely. I added a method that uses http.request to get data, which works and emit the data.
the problem is that the listener doesn't catch the event !
can someone help ?
code :
var events = require('events');
var util = require('util');
var http = require('http');
//http request options, it query the twitter api and get the public timeline, works!
var options = {
hostname : 'api.twitter.com',
port : 80,
method : 'get',
path : '/1/statuses/public_timeline.json?count=3&include_entities=true'
}
// The Thing That Emits Event
Eventer = function(){
events.EventEmitter.call(this);
//tutorial examples
this.kapow = function(){
var data = "BATMAN"
this.emit('blamo', data);
}
//tutorial examples
this.bam = function(){
this.emit("boom");
}
//my method
this.GetTweetList = function(){
var tweets = "";
var req = http.request(options, function(response){
var body = "";
response.on('data',function(data){
body += data;
});
response.on('end', function(){
tweets = JSON.parse(body);
this.emit("tweets", tweets);
util.puts('!!!!!!!!!! got some data !!!!!!!!!! \n');
});
});
req.end();
}
};
util.inherits(Eventer, events.EventEmitter);
// The thing that listens to, and handles, those events
Listener = function(){
//tutorial examples
this.blamoHandler = function(data){
console.log("** blamo event handled");
console.log(data);
},
//tutorial examples
this.boomHandler = function(data){
console.log("** boom event handled");
}
//my listener method
this.GetTweetListHandler = function(data){
console.log("** tweets event handled");
util.put(data);
util.puts('!!!!!!!!!! got some data in listener !!!!!!!!!! \n');
}
};
// The thing that drives the two.
//instanciating the object and liking the methodes
var eventer = new Eventer();
var listener = new Listener(eventer);
eventer.on('blamo', listener.blamoHandler);
eventer.on('boom', listener.boomHandler);
eventer.on('tweets', listener.GetTweetListHandler);
//calling the methodes
eventer.kapow();//works
eventer.bam();//works
setInterval(eventer.GetTweetList, 2000);
//eventer.GetTweetList();// still waiting but the eventer display that he got the data
Hard one to spot ...
The problem is the this pointer from this.emit("tweets", tweets);. You are doing this call from within an anonymous callback passed to response.on, so this does not represent the Eventer object that you created.
To solve it, you need to "save" the this pointer (a common practice).
var tweets = "";
var self = this;
....
self.emit("tweets", tweets);
i'm trying to write a simple app with node.js to pull some json from twitter..
json loads ok the first time, however, my 'tweets' event isnt getting triggered correctly..
anyone see where I'm going wrong? any advice hugely appreciated !
var twitterClient = http.createClient(80, 'api.twitter.com');
var tweetEmitter = new events.EventEmitter();
var request = twitterClient.request("GET", "/1/statuses/public_timeline.json", {"host": "api.twitter.com"});
function getTweats() {
request.addListener("response", function (response) {
var body = "";
response.addListener("data", function (data) {
body += data;
});
response.addListener("end", function (end) {
var tweets = JSON.parse(body);
if (tweets.length > 0) {
tweetEmitter.emit("tweets", tweets);
console.log(tweets, 'tweets loaded');
}
});
});
request.end();
}
setInterval(getTweats(), 1000);
http.createServer(function (request, response) {
var uri = url.parse(request.url).pathname;
console.log(uri);
if (uri === '/stream') {
var cb = function (tweets) {
console.log('tweet'); // never happens!
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(JSON.stringify(tweets));
response.end();
clearTimeout(timeout);
};
tweetEmitter.addListener("tweets", cb);
// timeout to kill requests that take longer than 10 secs
var timeout = setTimeout(function () {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(JSON.stringify([]));
response.end();
tweetEmitter.removeListener("tweets", cb);
}, 10000);
} else {
loadStaticFile(uri, response);
}
}).listen(port);
console.log("Server running at http://localhost:" + port + "/");
see full file # https://gist.github.com/770810
You have two problems here:
httpClient.request is just that, a one time request.
You're not passing the function getTweats to the interval, but its return value:
setInterval(getTweats() */ <-- parenthesis execute the function */, 1000);
In order to fix it, create a new request for each call of getTweats:
function getTweats() {
// There's no need for request being global, just make it local to getTweats
var request = twitterClient.request("GET", "/1/statuses/public_timeline.json", {"host": "api.twitter.com"});
And pass the function correctly to setTimeout:
setInterval(getTweats, 1000);
PS: Thx for the gist! Took me like 15 seconds to figure it out from there, always great when people post more than just 5 lines of out of context code :)