I am building a web app and one of the functionalities is to trigger an action in the backend which can take up to 5 minutes. This 'action' is a process which will run totally on its own (regardless of the front-end/back-end of my web app).
There is a form on the client-side which I use JavaScript to grab the data, clean it up/validate and send an Ajax call to my backend to start the process (which can take up to 5 minutes).
My question is, what if the user refreshes the page? The backend will still be triggered and run on its on, but I wanted to be able to capture the response back to the browser once the process is done in the back end. Is that viable/possible?
My Ajax is a pretty simple POST request to my backend:
$.ajax({
type: 'POST',
url: '/add-user',
data: {'data': JSON.stringify(data)},
//contentType: 'application/json;charset=UTF-8',
success: function(response){
console.log(response['message'])
}
//timeout: 3000 // sets timeout to 3 seconds
});
Please refer to this question prompt-user-before-browser-close
The only solution is to display a loading bar or spinner on the page while your page is waiting for the server task to finish.
If the user wants to navigate away you can use the confirm prompt.
I highly suggest using a websocket connection and if the user really closes, then inside window.onbeforeunload you should send a message and notify the backend to cancel the request context and stop the task from running. Running something like this without this protection can make your backend easy to get bombed.
PS. If it's a process independent of your backend then you should have scripts in place to kill it if the request context is canceled.
Related
I am building a application with many form submissions and using ajax to send data to server (node js). I have a table to be updated on a button click , and on click I need to load a spinner and call the ajax post request to server. On server it takes some time to update and send back result to ajax success. So on ajax success I hide the load spinner and update the data to table. Everything works fine problem is meanwhile when ajax req is called and server side is executing query the user may reloads the page, when page reloads ajax call is cleared so i cannot hide the load spin and update success data to html. What is the possible solution to avoid this
$.ajax({
url: url,
type: 'POST',
processData: false,
contentType: false,
data: formdata,
success: function (data) {
if (data.status == 'Success') {
toastr.success(data.msg);
// code to hide load spin
// update result data to html
}
})
You can do three things listed below in the order of complexity:
1. Put warnings on the page for users not to press reload or back buttons. This approach is often adopted on payment gateways when credit card details are verified server side. You can show a modal dialog box with the warning and spinner graphic.
2. Use session variables on server side to detect interruptions to ajax calls. For example you can have a variable called ajax_status (values none, incomplete and complete). You can set this variable at the start and successful completion of an ajax call. On page load, if you find the variable set to incomplete, show an error message, saying ‘something went wrong, have you pressed the reload button?’
3. Extend the 2nd approach to save ajax call parameters and reinitiate the request on page reload (show a warning saying data refresh was interrupted and reinforce message re not reloading).
You can avoid a page refresh(re-load) while all of your code is being executed by changing your html form action -
<form id="myForm" action="javascript:void(0)"></form>
This will also maintain HTML standards without fancy code to manipulate element functions.
I have the following AJAX call which needs up to 20 seconds to complete. I want the user to be able to leave the site while this call is loading and not finished.
However when the user clicks on a link or the back button the site is waiting for the call to finish before the user gets redirected to the previous site or the link the user clicked on
$.ajax({
url: 'index.php?route=sale/order/getSupportTickets&token=<?php echo $token; ?>&email=<?php echo $email; ?>',
dataType: 'json',
success: function(json) {
//do stuff here
}
});
An AJAX call is no different from a regular HTTP call (it just happens behind the scenes). As such the server is still executing this call (getSupportTickets).
It sounds like your web server is actually blocking (i.e. you don't have any threading support or the CPU is 100% busy) which is giving you this illusion of a blocking call
In your ajax call, use session_write_close(); once you got the data of the session you needed.
Only 1 php script can run with 1 php session at the same time, sessions are 'locked' to the current script. The scripts which use session_start() will be blocked on that instruction until the session is freed.
If you release the session by using session_write_close(); then your ajax script will be able to continue, while the new requests will be able to access the session (which is what was blocking).
On frontend (html file) I have a JS code which launches a POST request to node server,some processing takes place at the server end and after that the response is sent back.
The processing can take upto like half an hour also. But what happens is after just 5 minutes of not receiving response it resubmits a POST request, which is not what I want as it'll interrupt the backend processing.
My question is, is it possible to make this happen? If yes how?
Here's my fetch code
fetch('<url_here>', {
body: JSON.stringify(data),
headers: {
'content-type': 'application/json'
},
method: 'POST'
})
.then(response => response.json())
.then(res => {
//work with response data
});
Apparently, Fetch does not natively implement a way to set a timeout. Some people have developed workarounds.
However, I'm not sure this is the way to go. If your operation takes an hour and a half and you want to get the result whenever it is done, keeping your browser open and untouched for that long is complicated. What happens if the user closes the tab then reopens it, or refreshes the page? It will make a second call.
IMO the way to go is using websockets (socket.io) so the server can notify the client(s) whenever it's ready, and also send data along, even if the page has been refreshed in the meantime.
You can't.
If you need to do a lot of processing on the server, then break it up into parts.
Make a request to the server
Put the data in the request on a queue and give it an id
Pass the id back to the client
Have something monitoring the queue which processes data when you add some to it
When an item on the queue has been processed, mark it as complete
Communicate the result to the client
There are a few ways you could implement step 6. The simplest is to have the client poll, on an interval, the server with "Is the data for my id ready?". An alternative would be to use Web Sockets and push the response to the client when it is ready. If you want to wait for up to 90 minutes, then looking at Web Workers and the Notifications API would probably be wise too.
Here's an example. One user connects to the website and does some stuff. JS sends changes to PHP and it's processed. Say another user that connected at the same time needs to be notified of this change. So PHP somehow tells the second users browser through JS or something to change some HTML to the second user is aware of said changes. Is there a way I can do this? Or is it a no can do?
You need websocket (http://socketo.me/) to do that or use pusher (https://pusher.com/) to push something to client.
that would be done with Ajax or WEbSockets.
WebSocket works by opening a connection channel between the server and users.
you can find some websocket Examples Here:
http://www.websocket.org/demos.html
you can use this
$.ajax({
url: "url",
type: "POST",
data: params,
success: success(){},
error: error()
});
I'm attempting to AJAX in an MVC View to an empty tag using the standard jQuery AJAX call:-
function AjaxLoadPanel(url, id) {
var a = 1;
$.ajax({
url: url,
cache: true,
type: "GET",
success: function (data) {
if (data == "PageNotFound") {
window.location = "page-not-found";
}
else {
$(id).html(data)
}
},
error: function (response) {
$(id).html("");
}
});
}
The MVC controller simply returns the View with an MVC form within, and a HTTP Post beyond that to accept form data. When I put the pages with the div tag and the DLL and views on the server however, there is significant lag before the div tag is populated with the view return from the AJAX call. When I say significant lag, I mean 30 to 60 seconds after the page has loaded. The AJAX call does eventually finish, but such a problem renders the page useless to the unsuspecting user.
Stuff I've checked:-
All scripts are local to the site, no calls to external JS files.
All CSS are local to the site, no external calls.
The view and DLL's are definitely in the correct place
There are no scripts in the head tag.
The view does eventually get AJAX'd into the correct panel.
The wait time comes from calling the view specifically. Navigating to the URL of the view results in a 30 - 60 second wait before the view is returned.
How can I speed up the retrieval of the view? I need it to be within 1 second of page load if at all possible? Also, on localhost this feature works at lightning speed, loading in around 0.2 / 0.3 seconds.
Could it be the server being slow?
Thanks!
Mike.
Check your browser's network panel how long does the AJAX request takes to load.
I am quite sure it is problem with the backend/server. Are you 100% sure that the server backend code is same as your localhost backend code? Also do you use any database to retrieve the data. Could be also database issue.
We found the issue eventually. A datbase connection string login was wrong and the 30 second wait was always 30 seconds because of the length to try and connect to the database for, before causing an exception. At 30 seconds those views that don't directly rely on a database connection are still retrieved, hence the 30 second wait every time.
Thanks for your help!
Mike.