Basically I have client side javascript which sends post requests (through jQuery) triggered by user interactions with the page to my node.js server. The node.js server then handles the requests and updates content in the database.
For some reason, I am reaching a limit of the number of posts I can send to the server in a single page load. This maximum is 6. After 6 posts are sent from a page, I get these errors for trying to send any more requests:
EDIT:
These red errors are popping up in my Javascript console after trying to send more than 6 requests:
send jquery-latest.js:8526
jQuery.extend.ajax jquery-latest.js:7978
jQuery.(anonymous function) jquery-latest.js:7614
haveLikedOrDislikedObject
(anonymous function) localhost:33
fire jquery-latest.js:1037
self.fireWith jquery-latest.js:1148
done jquery-latest.js:8074
callback
My code for sending the post: (Basically a listener is attached to numerous divs, and when it is clicked a post request is sent)
//Sets on click listener for like button of content
$(document).delegate("div[id^='likeDiv']", "click", function() {
var el = this;
$.getScript("public/javascripts/load_content.js", function(){
haveLikedOrDislikedObject(0, $(el).attr('name'), theUser);
});
});
function haveLikedOrDislikedObject(res, contentNumber, user){
if(user != undefined){
if(res == 0){
$.post("/likeContent", { content: contentNumber, user: user.UserID });
$("#haveLikedDiv_" + contentNumber).text("You like this.");
} else{
$.post("/dislikeContent", { content: contentNumber, user: user.UserID });
$("#haveLikedDiv_" + contentNumber).text("You dislike this.");
}
} else{
$("#haveLikedDiv_" + contentNumber).text("Sorry, something went wrong.");
}
};
Just wondering why I would be getting this limit? Also, any thoughts on how I can go around this, or other ways to send numerous things to my server from a single page?
SOLVED:
Turns out I was not sending back anything from my server and I think this means each post was waiting for a response, therefore making 6 open requests. So, make sure that you are sending something back from the server, even if it is undefined like this:
app.post('/likeContent', function(req, res){
res.send(undefined);
});
Turns out I was not sending back anything from my server and I think this means each post was waiting for a response, therefore making 6 open requests. So, make sure that you are sending something back from the server, even if it is undefined like this:
app.post('/likeContent', function(req, res){
res.send(undefined);
});
Related
I wish to give the client feedback before a redirect occurs, so they can store it in session storage, then when the cached page arrive from the service worker, they check session storage while the page is being rendered (not after!), and can handle the cached response accordingly.
I tried:
Adding a custom header to the response, but the client JavaScript can't read it for security reasons.
I have tried to edit the response directly. This only works for GET requests. Unfortunately when I sync a POST request, because it returns a redirect, so then it looks like a normal GET. So I need some additional way of saying, this is a GET after a sync POST, tell the user the POST was saved, its not just a normal "get the page"
Post Message, but slow as.
LocalStorage and SessionStorage is forbidden for the service worker
I could write to IndexedDB in the service worker, and then read from the client. But IndexedDB is such a confusing beast I really don't want to go down this route.
URL search parameters, redirect and url cleaning strategy became spaghetti code very quickly. The server would have to clean up URLs, and so would the service worker for the injected query args.
Is there any recommended machanism for relaying information to a client that would suite this purpose?
Side note about the post message being slow:
I currently use post message, but the problem is its really slow, and the reason I think is this:
Client attempts offline POST
Service worker serializes and stores it for when online again. In the fetch interrupt it responds with the cached response. It also calls an async postmessage to tell the client it was saved. Unfortunately if I await the postmessage, it errors out the fetch. So then one has to leave it to be async. Which means the post message happens only after the redirect
Client receive redirect response
Client redirects
Client paints the page
The cahed paged is showed
Only after about two seconds later it shows the 'was saved banner'
Heres some code if applicable:
Note: Orginally the code would set a value in the session storage when receiving the message (assumed it would receive the message before the redirect), and then pop it after the redirect at page render. However because the post message was coming so much later, I changed to performing the change on the page directly.
async function msgClientSyncSaved(event) {
const data = {
type: 'MSG_SYNC_SAVED',
};
const client = await getClient(event);
client.postMessage(data);
}
// Applicable parts of runFetch:
async function runFetch(event) {
const urlObj = new URL(event.request.url);
if (utils.getIsMethodTx(event.request.method)) {
// If a Sync URL
const clonedRequest = event.request.clone();
const response = await new strategies.NetworkOnlyStratey(log, event, cacheMutator).run();
if (!response.isDefaultResponse && !response.isCachedResponse) {
event.waitUntil(syncAllRequests());
return response;
} else {
const [syncKey, syncValue] = settings.PWA_SYNC_POST_URL_PARAM.split("=");
if (urlObj.searchParams.get(syncKey) === syncValue) {
// A failed POST, that requires SYNCING
console.log(`SW: Sync later: ${event.request.method} to ${event.request.url}`);
event.waitUntil(storeRequest(clonedRequest)); // no need to wait for this to finish before returning response
event.waitUntil(msgClientSyncSaved(event)); <--- HERE message client
// After a post, return a redirect
urlObj.searchParams.delete(syncKey);
const redirectUrl = String(urlObj);
// 302 means GET the redirect, 307 means POST to the redirect
console.log('REDIRECT TO', redirectUrl)
return Response.redirect(redirectUrl, 302);
}
}
}
}
function handleFetch(event) {
event.respondWith(runFetch(event));
}
self.addEventListener("fetch", handleFetch);
Reciever on client side:
async function handleMessage(event) {
switch (event.data.type) {
case 'MSG_SYNC_SAVED':
document.body.setAttribute('data-pwa-cached-page', 'true data-tx')
break;
}
}
navigator.serviceWorker.addEventListener("message", handleMessage);
I'm trying to write a simple Node.js http server which stops and exits its process when a given url is accessed: in this case, /stop. This is my program so far:
var http = require('http');
var server = http.createServer(function(request,response) {
response.end(function(){
if (request.url === '/stop') server.close();
});
});
server.listen(12345);
What I expect to happen is that the callback is called when the response finishes sending, and the server closes if the URL is /stop. However, all this ends up doing is it shows a blank page (which I expected) and does nothing else.
On the other hand, this program almost works if I omit response.end():
var http = require('http');
var server = http.createServer(function(request,response) {
if (request.url === '/stop') server.close();
});
server.listen(12345);
It does manage to stop the server, but not until I terminate the GET request by closing the browser window.
How can I get the server to stop when I GET a certain URL without having to close the browser window? (It would be nice if I could send a "Server stopped" message to the browser, too.)
NOTE: I know that I don't actually have the code to differentiate between GET and POST requests, but I would like to be able to handle both, and I'm assuming the answer isn't different depending upon the type of request.
I send JSON requests one by one to the nodejs server. After 6th request, server can't reply to the client immediately and then it takes a little while(15 seconds or little bit more and send back to me answer 200 ok) It occurs a writing json value into MongoDB and time is important option for me in terms with REST call. How can I find the error in this case? (which tool or script code can help me?) My server side code is like that
var controlPathDatabaseSave = "/save";
app.use('/', function(req, res) {
console.log("req body app use", req.body);
var str= req.path;
if(str.localeCompare(controlPathDatabaseSave) == 0)
{
console.log("controlPathDatabaseSave");
mongoDbHandleSave(req.body);
res.setHeader('Content-Type', 'application/json');
res.write('Message taken: \n');
res.write('Everything all right with database saving');
res.send("OK");
console.log("response body", res.body);
}
});
My client side code as below:
function saveDatabaseData()
{
console.log("saveDatabaseData");
var oReq = new XMLHttpRequest();
oReq.open("POST", "http://192.168.80.143:2800/save", true);
oReq.setRequestHeader("Content-type", "application/json;charset=UTF-8");
oReq.onreadystatechange = function() {//Call a function when the state changes.
if(oReq.readyState == 4 && oReq.status == 200) {
console.log("http responseText", oReq.responseText);
}
}
oReq.send(JSON.stringify({links: links, nodes: nodes}));
}
--Mongodb save code
function mongoDbHandleSave(reqParam){
//Connect to the db
MongoClient.connect(MongoDBURL, function(err, db)
{
if(!err)
{
console.log("We are connected in accordance with saving");
} else
{
return console.dir(err);
}
/*
db.createCollection('user', {strict:true}, function(err, collection) {
if(err)
return console.dir(err);
});
*/
var collection = db.collection('user');
//when saving into database only use req.body. Skip JSON.stringify() function
var doc = reqParam;
collection.update(doc, doc, {upsert:true});
});
}
You can see my REST call in google chrome developer editor. (First six call has 200 ok. Last one is in pending state)
--Client output
--Server output
Thanks in advance,
Since it looks like these are Ajax requests from a browser, each browser has a limit on the number of simultaneous connections it will allow to the same host. Browsers have varied that setting over time, but it is likely in the 4-6 range. So, if you are trying to run 6 simultaneous ajax calls to the same host, then you may be running into that limit. What the browser does is hold off on sending the latest ones until the first ones finish (thus avoiding sending too many at once).
The general idea here is to protect servers from getting beat up too much by one single client and thus allow the load to be shared across many clients more fairly. Of course, if your server has nothing else to do, it doesn't really need protecting from a few more connections, but this isn't an interactive system, it's just hard-wired to a limit.
If there are any other requests in process (loading images or scripts or CSS stylesheets) to the same origin, those will count to the limit too.
If you run this in Chrome and you open the network tab of the debugger, you could actually see on the timline exactly when a given request was sent and when its response was received. This should show you immediately whether the later requests are being held up at the browser or at the server.
Here's an article on the topic: Maximum concurrent connections to the same domain for browsers.
Also, keep in mind that, depending upon what your requests do on the server and how the server is structured, there may be a maximum number of server requests that can efficiently processed at once. For example, if you had a blocking, threaded server that was configured with one thread for each of four CPUs, then once the server has four requests going at once, it may have to queue the fifth request until the first one is done causing it to be delayed more than the others.
In browser javascript is pathetically broken in that the only way to make requests is using script tags and jsonp. To make this useful, I'm trying to make a nodejs server that, given a callback name and address, loads the page at the address and pads it in a call to callback and serves the result. However, I know next to nothing about nodejs. If the server's response is loaded from a script tag it would result in actually loading a web page. Currently, I'm writing the request as localhost:8000/callback/address so a script tag might be <script src="localhost:8000/alert/https://www.google.com" type="text/javascript"></script>. Here is my code for the server:
var http = require("http");
var request = require("request");
var server = http.createServer(function(req, res){
req.on("end", function(){
console.log("alive");
var url = req.url;
var i = url.indexOf("/", 1);
request(url.substring(i + 1), function(err, ret, body){
res.writeHead(200);
res.write(url.substring(1, i) + "(\"" + body + "\");");
res.end();
});
});
});
server.listen(8000);
Why does this stay loading for a very long time but never actually load? By using console.log() it seems as if the req.on("end") callback is never even called.
If you don't care about any request data, you could just add req.resume(); after you add your end event handler.
The reason it's getting "stuck" is that since node v0.10, streams start out in a paused state, so you need to unpause them by reading from them in some way. req.resume(); accomplishes this. Once there is nothing left in the request stream (which there could be nothing), the end event will be emitted.
I have an ajax call for some data (using jQuery). after the user clicks "submit" (and the ajax call has been sent) I am displaying a "Please wait..." message that disables everything until the request returns (so the user won't double click or click other things and mess things up).
It works great when there is any kind of error - the "Please wait..." disappears and I am displaying the user what went wrong.
But what happens if the server don't return me anything back because of communication error?
The solution I found for that is to set a timeout of 10 seconds for the "Please wait.." message that after that time it disappears and displays and error that "The communication failed". I assume that if the server didn't respond after 10 seconds then it will not respond at all - but that it false assumption.
The problem is - how can I be sure that after 20 seconds the server won't return something back? The scenario that might happen is that the user click submits --> 10 seconds later he get an error message --> 5 seconds later server response and confuses the user
How do I make sure that after I hide the "Please wait.." message nothing will pop up from the server?
when you send a request to a server. a connection is opened and its kept open unless the server responds.
1.if due to some error on the server side it cannot respond then a response code of 5xx is sent back generally (503)
2.if due to some connection issues the connection is terminated prematurely then also jquery would take that as an error.
1.so if you wanna wait for the server to send a request or connection termination (which ever occurs earlier) then u can use the completed option in the jquery ajax.
2.and if you are in a condition in which server isnt responding even after 20 secs and you think that it should have responded by now use timeout.
3.finally if your problem is that you are using some kind of customized(hand made http server) which doesn't end a request even if it encounters some error then atleast customize it enough so that it sends back some response code(because this is HTTP model of request and response)
You can handle something like this
if ( request.readyState == 4 ){ // 4 is "complete"
if ( request.status == 200 ){
// HTTP OK, carry out your normal Ajax processing
// ...
}else{
// something went wrong, report the error
error( "HTTP "+request.status+". An error was ยป
encountered: "+ request.statusText );
}
}
(or)
$.ajax({
type: "post",
url: "somepage.html",
success: function (data, text) {
//...
},
error: function (request, status, error) {
alert(request.responseText);
}
});
Generate a unique token when you fire a request,
keep a list of valid tokens,
remove tokens when the request times out/fails,
check if token is still valid before executing success/error callbacks.
The same pattern can be adapted for a situation when you need to send frequent repeating requests (e.g. autocompletion/result filtering) and only the latest one's handler should fire.