nodejs - why does my async function run twice? [duplicate] - javascript

This question already has answers here:
nodejs - http.createServer seems to call twice
(3 answers)
Closed 6 years ago.
I am new to node.js and learning from tutorials online.
I was trying out the following piece of code :
var http = require("http");
// create a server
http.createServer(function(req, res) {
console.log("Received Request");
res.writeHead(200, {'Content-Type':'application/json'});
res.end("{'status':'200', 'message':'Hello World'}");
console.log("Response Sent");
}).listen(process.env.PORT, process.env.IP);
I did receive the correct response but in console the output was :
Received Request
Response Sent
Received Request
Response Sent
I wanted to know why was my code running twice ?? Am I making some mistake ?
Please help !!

the best way to debug is to check the url
var http = require("http");
// create a server
http.createServer(function(req, res) {
console.log(req.url);//add this line, I hope it will help
console.log("Received Request");
res.writeHead(200, {'Content-Type':'application/json'});
res.end("{'status':'200', 'message':'Hello World'}");
console.log("Response Sent");
}).listen(process.env.PORT, process.env.IP);
Also as Bassam Rubaye pointed out it might most likely due to favicon in your case

When you access a url using the browser , the browser will send a request for the favicon, then send another request for the content, that's why you are seeing two requests !
Use PostMan and request the same url , you should see only one request.

No mistake--this is normal! Your browser makes multiple requests. There's a similar answer at nodejs - http.createServer seems to call twice.
Hope you're having fun learning node.js!

Related

nodeJs how to make http post request execute [duplicate]

This question already has answers here:
How to wait until a predicate condition becomes true in JavaScript?
(23 answers)
How to prevent Node.js from exiting while waiting for a callback?
(8 answers)
Closed 2 years ago.
I have narrow down my problem to this,
I want to send post request to an API server but the post request sent only after the program exits.
my main.js:
var request = require("request");
send_post_to_server = function(name, responseCallback, outconfig) {
var outconfig = outconfig || {...};
request.post({
url: 'http://localhost:3000/api/backtest',
json: outconfig
}, function optionalCallback(error, response, body) {
responseCallback(error, response, body);
});
}
send_post_to_server ('first post request', my_response_callback);
send_post_to_server ('second post request', my_response_callback);
while(true); // with the loop, the server never gets the post requests.
If I remove the while loop and the program exits, it dose work and I do get the response to optionalCallback and responseCallback. But with the loop, the server dose not get the request.
why is that happened? and how can I make the program send the request? some kind of flush?
to run the program I use:
node main.js and npm istall request for the request module.
Because while(true); is blocking the thread and Node.js using single thread. Prefer asynchronous to do the operation. See also: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
If you want to keep the Node.js process not terminating there is an answer for this
How to forcibly keep a Node.js process from terminating?

Why is there a double console.log? [duplicate]

This question already has answers here:
node.js beginner - why does this receive 2 responses?
(1 answer)
Why does node.js, http-server, show that there are two request coming?
(1 answer)
Closed 7 years ago.
Description:
Hello, following a simple and straight forward tutorial. Everything works fine, but I was just curious as to why I'm getting a double request received when I refresh/access my page?
Part of my code:
function onRequest(request, response){
console.log('request received');
response.writeHead(200, {"Content-Type": "text/plain"});
response.write('Hello world baby');
response.end();
}
//creating server
http.createServer(onRequest).listen(8888);
console.log("server has started");
Screenshot:
Your browser is looking for the favicon.ico, then it sends a request for the actual content. Try to console.log both the request and response to get more information.

NodeJS HTTP request from AngularJS

I'm currently developing a web application using AngularJS on the fronted and NodeJS on the backend with express. I've had trouble requesting my backend API from the fronted however and hope you guys can help me.
Backend (NodeJS):
app.get('/test', function(req, res) {
res.json(200, {'test': 'it works!'})
})
Frontend (AngularJS):
myApp.controller('myController', function($scope, $http) {
delete $httpProvider.defaults.headers.common["X-Requested-With"]
$http.get('http://localhost:5000/test').success(function(data) {
alert('Success')
}).error(function(data, status) {
alert('Error! ' + status + ' : ' + data)
})
})
When I refresh the app I get an alert saying: Error! 0 :, however, when I request the backend with curl or by the browser, I get the test dict back. The frontend seems to be able to access the backend though because I see it in my backend log that it's done a request and got something back, but firebug says that the response is empty, what should I do?
Thanks so much, let me know if you need more info from me.
Mattias
Make sure that your frontend and backend servers have the same origin (protocol, host and port). If not, then you does not recieve response since you make cross-origin ajax request. In this case you should send special header from your backend to allow it:
Access-Control-Allow-Origin: *
You can add response header with the following code:
res.set('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Origin', '*');
Use res.status(status).json(obj) instead of res.json(status, obj)

node.js receiving POST data submitted through form using HTTP

I'm using a node.js server and need to post data over an http*s* protocol.
POST is listed as a http protocol, so I'm wondering if I'm on the wrong track.
Anyway, here is the top of my code that handles the POST. I've not included the on('end') function for berevity, but it is there.
exports.login = function(req, res){
if(req.method == 'POST'){
var datastring = '';
req.on('data', function(data){
datastring += data;
console.log("getting data");
if(datastring.length > 1e6){
req.connection.destroy();
}
});
Through console logs I can determine that the request is being made, and that the request is recognised as POST, but that req.on('data')'s function is never called.
I looked into a CONNECT protocol, but this isn't supported by browser forms - please advise how to send data through CONNECT if you don't think I can send POST data over HTTPS
Thanks for your help
EDIT: here is form that sends request:
<form name="loginForm" action="login" method="POST" onsubmit="return checkForm()" class="separate-sections">
and here is node.js code that grabs post
var app= express();
...
app.post('/login', route_login.login);
To make a long story short, does POST work over HTTPS? It doesn't seem to be working here.
Found out someone on my team had added the express bodyparser, so naturally posts no longer work in the way I had before. The change just happened to coincide with when we switched to https which made it look as if this was the issue, when it was not.

Basic Ajax send/receive with node.js

So I'm trying to make a very basic node.js server that with take in a request for a string, randomly select one from an array and return the selected string. Unfortunately I'm running into a few problems.
Here's the front end:
function newGame()
{
guessCnt=0;
guess="";
server();
displayHash();
displayGuessStr();
displayGuessCnt();
}
function server()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","server.js", true);
xmlhttp.send();
string=xmlhttp.responseText;
}
This should send the request to server.js:
var http = require('http');
var choices=["hello world", "goodbye world"];
console.log("server initialized");
http.createServer(function(request, response)
{
console.log("request recieved");
var string = choices[Math.floor(Math.random()*choices.length)];
console.log("string '" + string + "' chosen");
response.on(string);
console.log("string sent");
}).listen(8001);
So clearly there are several things going wrong here:
I get the feeling the way I am "connecting" these two files isn't correct both in the xmlhttp.open method and in using response.on to send the string back to the front end.
I'm a little confused with how I call this page on localhost. The front end is named index.html and the sever posts to 8001. What address should I be go to on localhost in order to access the initial html page after I have initialized server.js? Should I change it to .listen(index.html) or something like that?
are there other obvious problems with how I am implementing this (using .responsetext etc.)
(sorry for the long multi-question post but the various tutorials and the node.js source all assume that the user already has an understanding of these things.)
Your request should be to the server, NOT the server.js file which instantiates it. So, the request should look something like this: xmlhttp.open("GET","http://localhost:8001/", true); Also, you are trying to serve the front-end (index.html) AND serve AJAX requests at the same URI. To accomplish this, you are going to have to introduce logic to your server.js that will differentiate between your AJAX requests and a normal http access request. To do this, you'll want to either introduce GET/POST data (i.e. call http://localhost:8001/?getstring=true) or use a different path for your AJAX requests (i.e. call http://localhost:8001/getstring). On the server end then, you'll need to examine the request object to determine what to write on the response. For the latter option, you need to use the 'url' module to parse the request.
You are correctly calling listen() but incorrectly writing the response. First of all, if you wish to serve index.html when navigating to http://localhost:8001/, you need to write the contents of the file to the response using response.write() or response.end(). First, you need to include fs=require('fs') to get access to the filesystem. Then, you need to actually serve the file.
XMLHttpRequest needs a callback function specified if you use it asynchronously (third parameter = true, as you have done) AND want to do something with the response. The way you have it now, string will be undefined (or perhaps null), because that line will execute before the AJAX request is complete (i.e. the responseText is still empty). If you use it synchronously (third parameter = false), you can write inline code as you have done. This is not recommended as it locks the browser during the request. Asynchronous operation is usually used with the onreadystatechange function, which can handle the response once it is complete. You need to learn the basics of XMLHttpRequest. Start here.
Here is a simple implementation that incorporates all of the above:
server.js:
var http = require('http'),
fs = require('fs'),
url = require('url'),
choices = ["hello world", "goodbye world"];
http.createServer(function(request, response){
var path = url.parse(request.url).pathname;
if(path=="/getstring"){
console.log("request recieved");
var string = choices[Math.floor(Math.random()*choices.length)];
console.log("string '" + string + "' chosen");
response.writeHead(200, {"Content-Type": "text/plain"});
response.end(string);
console.log("string sent");
}else{
fs.readFile('./index.html', function(err, file) {
if(err) {
// write an error response or nothing here
return;
}
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end(file, "utf-8");
});
}
}).listen(8001);
console.log("server initialized");
frontend (part of index.html):
function newGame()
{
guessCnt=0;
guess="";
server();
displayHash();
displayGuessStr();
displayGuessCnt();
}
function server()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","http://localhost:8001/getstring", true);
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
string=xmlhttp.responseText;
}
}
xmlhttp.send();
}
You will need to be comfortable with AJAX. Use the mozilla learning center to learn about XMLHttpRequest. After you can use the basic XHR object, you will most likely want to use a good AJAX library instead of manually writing cross-browser AJAX requests (for example, in IE you'll need to use an ActiveXObject instead of XHR). The AJAX in jQuery is excellent, but if you don't need everything else jQuery offers, find a good AJAX library here: http://microjs.com/. You will also need to get comfy with the node.js docs, found here. Search http://google.com for some good node.js server and static file server tutorials. http://nodetuts.com is a good place to start.
UPDATE: I have changed response.sendHeader() to the new response.writeHead() in the code above !!!
Express makes this kind of stuff really intuitive. The syntax looks like below :
var app = require('express').createServer();
app.get("/string", function(req, res) {
var strings = ["rad", "bla", "ska"]
var n = Math.floor(Math.random() * strings.length)
res.send(strings[n])
})
app.listen(8001)
https://expressjs.com
If you're using jQuery on the client side you can do something like this:
$.get("/string", function(string) {
alert(string)
})
I was facing following error with code (nodejs 0.10.13), provided by ampersand:
origin is not allowed by access-control-allow-origin
Issue was resolved changing
response.writeHead(200, {"Content-Type": "text/plain"});
to
response.writeHead(200, {
'Content-Type': 'text/html',
'Access-Control-Allow-Origin' : '*'});
Here is a fully functional example of what you are trying to accomplish. I created the example inside of hyperdev rather than jsFiddle so that you could see the server-side and client-side code.
View Code:
https://hyperdev.com/#!/project/destiny-authorization
View Working Application: https://destiny-authorization.hyperdev.space/
This code creates a handler for a get request that returns a random string:
app.get("/string", function(req, res) {
var strings = ["string1", "string2", "string3"]
var n = Math.floor(Math.random() * strings.length)
res.send(strings[n])
});
This jQuery code then makes the ajax request and receives the random string from the server.
$.get("/string", function(string) {
$('#txtString').val(string);
});
Note that this example is based on code from Jamund Ferguson's answer so if you find this useful be sure to upvote him as well. I just thought this example would help you to see how everything fits together.

Categories

Resources