Node.js Express block - node.js

My Problem is, that I'm planning to use express to cache all requests which I receiver for a certain amount of time until I send all responses at once.
But unfortunately I can't receive a second request until I've responded to the first one. So I guess node / express is somehow blocking the further processing of other requests.
I build a minimal working example for you, so you can see better what I'm talking about.
var express = require('express');
var app = express();
var ca = [];
app.get('/hello.txt', function(req, res){
ca.push(res);
console.log("Push");
});
setInterval(function(){
while (ca.length) {
var res = ca.shift();
res.send('Hello World');
console.log("Send");
}
},9000);
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
});
When I'm sending just one request to localhost:3000 and wait for 9sec I'm able to send a second one. But when I send both without waiting for the callback of the interval, the second one is blocked until the first interval triggered.
Long Story short: Why is this blocking happening and what ways are there to avoid this blocking.
PS: It seems that the default http package shows another behavior http://blog.nemikor.com/2010/05/21/long-polling-in-nodejs/

try it with firefox and chrome to prevent serializing the requests...

OK, I've got the solution.
The issue wasn't in my code, it was caused by Chrome. It seems that Chrome is serializing all requests, which target the same URL. But nevertheless it sends both request and won't serve the second request with the response of the first.
Anyway, thanks for you help!

Related

NodeJS http request event listener firing more than once

I'm new to backend development so have just made my first server using NodeJS and the http module. This is my code so far:
const http = require("http");
let count = 0;
const server = http.createServer((req, res) => {
res.write(count.toString());
//tells the server that all of the headers and body have been sent, so the message is complete
res.end();
count += 1;
});
server.listen(3000);
I understand how almost all of this code works. However, whenever I refresh the page on my local environment (send a new request) I would expect the displayed response to increment by 1, however, it increments by 2. The only reason I can think this would happen is that the request event listener is being fired twice on each page reload, however, I cannot find anything to help me with this issue so any help would greatly be appreciated.
If i understand what this website says https://www.w3schools.com/nodejs/met_http_createserver.asp
The requestListener is called every time a request is sent to the server.
You can check in your Navigator console (in the Network sub-tab) the different requests sent to your server.
Maybe there are multiple requests sent to your server on page reload.
I hope this helped, otherwise, you can try to log in your requestListener the req object to know what triggers it, and where does it come from.

Sending multiple responses with the same response object in nodejs

I have a long running process which needs to send data back at multiple reponse. Is there some way to send back multiple responses with express.js
I want have "test" after 3 seconde a new reponse "bar"
app.get('/api', (req, res) =>
{
res.write("test");
setTimeout(function(){
res.write("bar");
res.end();
}, 3000);
});
with res.write a wait a 3050 of have a on response
Yes, you can do it. What you need to know is actually chunked transfer encoding.
This is one of the old technics used a decade ago, since Websockets, I haven't seen anyone using this.
Obviously you only need to send responses in different times maybe up to some events will be fired later in chunks. This is actually the default response type of express.js.
But there is a catch. When you try to test this, assuming you are using a modern browser or curl which all of them buffer chunks, so you won't be seeing expected result. Trick is filling up chunk buffers before sending consecutive response chunks. See the example below:
const express = require('express'),
app = express(),
port = 3011;
app.get('/', (req, res) => {
// res.write("Hello\n");
res.write("Hello" + " ".repeat(1024) + "\n");
setTimeout(() => {
res.write("World");
res.end();
}, 2000);
});
app.listen(port, () => console.log(`Listening on port ${port}!`));
First res.write with additional 1024 spaces forces browser to render chunk. Then you second res.write behaves as you expected. You can see difference with uncommenting the first res.write.
On network level there is no difference. Actually even in browser you can achieve this by XHR Object (first AJAX implementation) Here is the related answer
An HTTP request response has one to one mapping. You can return HTTP response once, however long it may be. There are 2 common techniques:
Comet responses - Since Response is a writable stream, you can write data to it from time to time before ending it. Ensure the connection read timeout is properly configured on the client that would be receiving this data.
Simply use web sockets - These are persistent connection that allow 2 way messaging between server and client.

aws x-ray tracing breaks on outgoing requests in Node.js

Hey I'm trying to trace outgoing requests from an express app, but I can't get it to work.
When I dont use the AWSXRAY.captureHttpsGlobal function everything works fine with incoming requests and I can see my application in "Service Map" and my incoming request traces coming in on AWS, but I want to trace outgoing requests and as soon as I add AWSXRAY.captureHttpsGlobal then nothing works and I get no exception or anything, and my Daemon doesnt print the usual "Successfully sent batch of 1 segments (0.058 seconds)"
This is my code.
var AWSXRay = require('aws-xray-sdk');
const express = require("express");
var app = express();
app.use(AWSXRay.express.openSegment('MyApp'));
AWSXRay.captureHTTPsGlobal(require('https')); // works when i comment this out
var http = require('https');
app.get('/', function (req, res) {
http.get("https://google.com", (resp) => {
res.send("googlefetched")
});
//res.send("hello world")
});
app.use(AWSXRay.express.closeSegment());
app.listen(3000, () => console.log('Example app listening on port 3000!'))
could you share which node runtime version your code is running at and which X-Ray SDK version you are using so we can try to reproduce this issue on our side?
At the meantime I would like to share a previous issue that has been fixed since v1.2.0 https://github.com/aws/aws-xray-sdk-node/issues/18 where if the response body is not consumed then the entire segment will never be flushed to the daemon.
Please let me know.

Using Node, Express, (and Socket.io?) to update a page every 1 second

I am a bit new to Node.js and Express, and am currently working on a page where I would like to generate and send messages (from the server) to the client page every 1 second (1250ms, actually). When a user visits the site, I would like the latest message to be broadcasted, with new messages coming in every second after. In other words, every user would see the same message at the same time on the web page, regardless of when they connected to the server.
I have done some searching and have unfortunately have not had any luck playing with code samples online. Here is a ROUGH IDEA to explain:
app.js
'use strict';
var express = require('express');
var app = express();
var http = require( "http" ).createServer( app );
var io = require( "socket.io" )( http );
app.get('/', function (req, res) {
res.sendFile(__dirname + '/public/index.html');
});
http.listen(3000, function(){
/* someFunction to generate new LATESTMESSAGE every 1s */
io.on('connection', function (socket) {
socket.emit('news', { messages: LATESTEMESSAGE })
});
});
I assume I would need to send the message via socket.io from the function that generates the LATESTMESSAGE (every 1s when message is generated, send via socket?)? If that is the case, I am unfamiliar with how I would require socket.io in a page that is NOT the app.js (this function would probably be a class, in its own js file), as socket.io requires app and express (see code above).
I appreciate the help! I have spent a good amount of time pondering this today and would appreciate any direction or assistance. Please let me know if I have not supplied enough information.
p.s. the code above definitely would not accomplish what is needed. just a rough outline to show what i am attempting to accomplish
What you're doing looks like half-duplex communication i.e. Only the server sends data to the client, and not the other way around. Socket.io is full duplex communication, i.e. Server and client send data to each other. So technically what would be best for your requirements is Server Sent Events (SSE) using EventStream. Socket.io might be slightly excessive.
Having said that, what you want is to write a Middleware, to which you pass the application. Please take a look at https://expressjs.com/en/guide/using-middleware.html
Basically, your io would be passed in to the middleware functions, so they'd have access to Socket. And the middleware functions in turn would be imported into your app.js.

How to send a temporary chunk of html and js to a running app on node.js

I just got my first app up and running on Node.js. As of now, it is simply serving up a static file. But I have a few ideas that will be implemented down the road so I'm going ahead and getting Node setup so I'll be ready for it when that time comes.
// get modules
var express = require('express');
var fs = require('fs');
// create app instance
var app = express();
// static files middleware
app.use("/assets", express.static(__dirname + '/assets'));
// main route
app.get('/', function(req, res) {
var html = fs.readFileSync('assets/views/main.html', 'utf8');
res.send(html);
});
// make web server listen on specific port
app.listen(8080);
NOTE: I realize I don't need Express to serve one route, but I figured what's the harm in getting a head start on that as well?! :)
The first idea i had is to make a way to let all users currently using the app that there has been an update and that they must refresh their browser. There is no need to save the current state of the app as it is pretty basic.
So, if I am a user, I'm using the app and boom, I get a pretty little modal-window-alert-notification thingy letting me know that I need to refresh.
Also, if some user loads the app AFTER I have sent the alert, that user should not see the alert at all (because they should already be seeing the new changes).
I have done some googling on the subject and I'm just not satisfied with the examples i found. I do not think I want to have to update a notifications.xml file (which node.js would be watching) to push a new notification.
One solution I can think of would be to make a command that can be executed from the command line that will (somehow) send a new notification to the app. Perhaps using something like Grunt.js (I'm not sure if it would be a good fit for this as I've never used it). Basically, once the notification has been sent, all traces of it should disappear. That's why I think a command line approach would be good.
Here's my question: How (generally speaking) should I implement something like this? I am a Node.js newbie but I am pretty comfortable with javascript and the command line.
Please feel free to offer up any alternative solution you think would be better for me (other than a command line approach), or any tools that you think could help me.
Thanks!
If you want to push updates to a web client, one way is to use something like Socket.io. This creates a two-way pipe between client and server that you can use to asynchronously push updates through.
Sample server:
var app = require('express').createServer()
, io = require('socket.io').listen(app);
app.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Sample client:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
alert('New news has come in! Please refresh your page!');
socket.emit('my other event', { my: 'data' });
});
</script>
The other option is to poll from the client using Javascript to actively look for updates. You would need to keep some state on the server for each client that would determine if that client required an update. The client would then make a get request on some timer interval (once a second, for example) to a secondary route and the server would reply with 'Yes, you need an update' or 'No, you don't need an update'. If yes, the client Javascript would then pop up your modal box and tell the user to refresh.

Resources