Javascript not proceeding aynchronously beyond AJAX call - javascript

When the user presses the 'Process' button on my application, I would like the application to trigger an AJAX request and then immediately redirect the user to another screen without waiting for the results of the AJAX request. I believe I have coded it appropriately but I notice that the screen is waiting for the AJAX to finish before redirecting. Am I missing something below?
$('#process-btn').on('click', function()
{
// disable the process & cancel buttons to prevent
// double submission or interruption
$('#cancel-btn').addClass('disabled');
$(this).addClass('disabled');
// trigger the AJAX require to process the uploaded file on the server side
$.ajax({
url: $('#form').attr('action'),
type: 'post',
data: $('#form').serialize(),
success: function() {
//on success
}
});
// redirect the user to view list
// this line is not being called immediately -
// this is being called only after AJAX returns
window.location.replace( www_root + 'Home/index' );
});

Because the button you have this handler hooked to is a submit button for a form (per your comments) and you aren't preventing the default behavior of that button, then the form submit will happen immediately and when the submit returns, it will change the page regardless of what your code tries to do.
So, the issue is that the returned form submit was overcoming what your code was trying to do.
You may be living a little dangerously by redirecting before your ajax call has finished. It's possible the browser could drop the ajax connection before the TCP buffers had actually been sent as TCP often has a small delay before sending buffers in order to collect consecutive data into common packets. It would be much safer to either redirect after a short timeout or redirect on the complete event which will be called regardless of ajax success.
If you really want to do the redirect BEFORE the ajax call has completed, you can experiment with the timeout value (shown here as set to 500ms) in this code to see what works reliably in multiple browsers:
$('#process-btn').on('click', function(e) {
// prevent default form post
e.preventDefault();
// disable the process & cancel buttons to prevent
// double submission or interruption
$('#cancel-btn').addClass('disabled');
$(this).addClass('disabled');
// trigger the AJAX require to process the uploaded file on the server side
$.post($('#form').attr('action'), $('#form').serialize());
// redirect the user to view list
// this being called after a short delay to "try"
// to get the form ajax call sent, but not "wait" for the server response
setTimeout(function() {
window.location.replace( www_root + 'Home/index' );
}, 500);
});
Also, note that I've added an e.preventDefault() and added the e argument to the event handler to make sure the form is not posted by default, only by your ajax code.
And, the timeout time is set here to 500ms. What you need is enough time for the TCP infrastructure in the host computer to send all your form data before you start the redirect. I see a mention of a "file upload" in your comments. If this form is actually uploading a file, that could take way, way longer than 500ms. If it's just sending a few form fields, that should go pretty quickly assuming there are no connection hiccups.
Caveat: Doing it this way is not the 100% reliable way of getting data to your server. There can easily be some conditions where it takes longer than usual just to do a DNS lookup before connecting with your server or your server could momentarily take longer to respond to the initial connection before data can be sent to it. The only 100% reliable way is to wait until the ajax call has succeeded as mentioned elsewhere.
You could perhaps have the best of both worlds (reliability + fast response) if you changed the way your server processes the ajax call so that as soon as it has received the data, it returns a successful response (e.g. in milliseconds after receiving the data) and then after it has sent back the successful response so the browser can then reliably do its redirect, it takes it's 2-3 minutes to actually process the data. Remember, you don't gave to wait until you are done processing the request to return a response. Then, you know that the server has received the data, but the browser doesn't have to wait for the processing time. If you don't always want this ajax call to work that way, you can pass an argument to the ajax call to instruct the server whether you want the fast response or not.

Why not try this:
$.ajax({
url: $('#form').attr('action'),
type: 'post',
data: $('#form').serialize(),
success: function() {window.location.replace( www_root + 'Home/index' );}
});

Related

Data loss when request get cancelled using AJAX in Laravel

I'm sending a big amount of data with POST using ajax in Laravel.
When I send request rapidly and redirect the page to another page then data is getting lost when ajax call is canceled or aborted.
I've mentioned the process below:
Send ajax request rapidly
Then before responding to latest request of ajax call by browser I redirect to another page
Then I check the data which is storing when ajax call happen. I found the data is lost.
Below is the code
<script>
var cssData = $('.css-textarea').val();
$.ajax({
url: '/save-data',
type: 'POST',
data: {cssData: cssData},
success:function(response){
//do something after success
}
});
</script>
PHP/Laravel Code
public function saveCssData(){
$data = Input::get();
$cssData = $data['cssData'];
//Do something to save data
$db->cssData = $cssData;
$db->save();
}
Please do not assume the exact code because I've given an example.
This code works fine but when I send rapid calls by ajax and before getting a response, I redirect to another page then the data is lost. I've set enough post_max_size and other configurations but still, it's not fixed
Example of Input which I am sending by ajax request
{
"testCss":
" #class{background:#fff}../*big amount data */...
#testDiv{color:#000}
"
}
Example of The Output which I am receiving in database which is lost
{
"testCss":
" #class{background:#fff}../*big amount data */...
#testDiv{col
You can see the data is lost in output. This issue is appearing at sometimes but I noticed that when I request rapidly with ajax and abort the requests by redirecting to another page then it's appearing but don't know how to fix this.

Javascript ajax request callback without waiting for response

I know we can make a javascript ajax request from some server and it either receives the response or gives timeout error after some time.
Let's consider this scenario when we don't want to wait for the request rather the server would send a response(or we can say it would be another request from server to client) async at any time after getting the request and then call a javascript CB function with the response.
I am looking for ideas for how to go about it mainly supporting all modern browsers and if possible not relying on any 3rd party plugin except may be jQuery.
The main feature of Ajax is that it IS asynchronous by default, and your program will continue to run without waiting for the response. So unless I'm misreading your question, it is what you need.
If you use jquery, then you pass in a callback function that will execute only when the server sends back a response. You can specify a timeout in the settings, though I'm not sure what the maximum time you can provide without getting a timeout error. But it will be several seconds, at least.
You can even specify different callbacks for success and fail as follows (adapted from the jquery ajax API, but added a timeout of 5 seconds):
var request = $.ajax({
url: "http://www.some.url/",
method: "GET",
data: { some : stuff },
dataType: "html",
timeout: 5000
});
request.done(function( data ) {
console.log( "SUCCESS: " + data );
});
request.fail(function() {
console.log( "Request failed");
});
I came across this question after 4 years. I dont remember in what context I asked this but for anyone who has the same query:
Http is a request/response protocol. Which means the client sends a request and the server responds to that request with some message/data. Thats the end of the story for that request.
In order for the server to trigger something on the clientside we will have to use something that keeps the connection to the server rather than ending the communication after getting the response. Socket.io is bi directional event driven library that solves this problem.
To update a cart (PHP Session storage and reserve the stock of items in database) on my online shop, I simply add a timeout of 100ms after calling it and remove Success/Error callback.
$.ajax({
url: 'http://www.some.url/',
method: 'GET',
data: {
some : 'stuff'
},
dataType: 'html',
timeout: 100
});
Note : It doesn't matter if some requests didn't arrive, because when the order is saved, an update of the whole cart is sent with a callback.
If your query needs acknowledge, don't use that solution !
I believe your question is similar to this
by Paul Tomblin. I use the answer provided by gdoron, which is also marked as the best solution, and also the comment by AS7K.
$.ajax({
url: "theURL",
data: theData
});
NB: No async parameter provided.

How to cancel MVC action if I use AJAX to call it?

I have an AJAX function on a view that calls an Action on one of my controllers to get a JSON object. The problem is that it takes a while to create the object. If the user reloads the page, then the AJAX call runs again. As far as I can tell the action is still running from the last request, but the response is no longer relevant because the new AJAX call is waiting for the new response.
My question is, how do I keep the action from continuing if the user leaves the view that called it?
Ajax:
$.ajax({
type: "get",
url: "/Alert/GetWallboardAlerts",
cache: false,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (result) { ... }
});
Controller action:
public ActionResult GetWallboardAlerts()
{
//...do long running stuff
//...still doing stuff when page reloaded or I navigate elsewhere
return Json(alertString, JsonRequestBehavior.AllowGet);
}
I don't think you can. Once you made a request to the server, you could close the browser but the request will still be executed.
This is just an idea:
1) Caller makes an AJAX request and provides a unique value (could be a guid).
2) Handle the page reload event and the close event and send a new AJAX request with the same unique key requesting a cancellation.
3) The long process task that is executed on the server should check for a flag that indicates that the task has been canceled.
You could also use a WebSocket for a task like this so the server could ping the client (like a "still alive" request). If you are using .NET you could use SignalR.
I hope it helps or at least it gives an idea to solve your problem.

Technique for 'Locking' a User's Actions During AJAX Calls

Often times I find myself designing apps that make AJAX calls to the server, outside APIs, HTTP requests, etc. The problem is, while this async calls are happening, the user still has the ability to click on items that make the same AJAX call or interrupt the flow of the app, etc. I've experimented with various hacks to prevent this, but I'm wondering what the most accepted way of doing this is?
To make this more concrete, let's say I have a button element that makes an AJAX call and a form element that alters some of the data my app uses for the AJAX call. What is the best way to design the button and form functions so that they do not work while button's AJAX call is in process?
The best way to accomplish what you want is to lead the AJAX calls trough a function so you can check within that function if a request is active. Here's an example assuming you're using JQuery:
active_ajax_call = false;
function get_ajax(url, senddata) {
if(active_ajax_call == false) {
active_ajax_call = true;
$.ajax({
type: "POST",
url: url,
data: senddata
}).done(function (data) {
active_ajax_call = false;
console.log(data);
});
}
}
get_ajax("some_url", {name: "John", location: "Amsterdam"});
And ofcourse present the website user a nice ajax loader or something so they know data is being pulled.
In the handler for the button, disable the button (visually and functionally), then do the AJAX call. Returning from the AJAX call, reenable the button.
This is, how the major sites do it (e.g. PayPal).

Keep Track Of Ajax Request

Newbie here..
I just want to ask how can I accomplish my homework in school.
I basically have this need.
I want to send an ajax request every 10 seconds but I dont want to initiate another request if my previous request has not returned yet.
I am thinking that the connection to DB might be that bad sometimes so I would like to wait for my previous request to be finished (success/failed/error) before I fire up another.
I check on javascript and and found the setinterval method. But how can I line up my ajax request so that the server doesnt get fired up by many ajax request?
I am studying jquery right now and is using JSON.
One method would be to set a variable to false when you send out a request. When you get it back set it back to true. When you go to send out a new ajax request make sure the value is true. If not add it to a queue of some sort so that it will be called when the request is finished. However if every request takes longer then ten seconds your queue will get pretty backed up. So you may not want a queue. So instead when you go to send out the ajax request if the variable is false you just wait another ten seconds.
I'll even help more:
var isWatingForResponse = false;
$.ajax({
url: 'wherever'
,dataType: 'json'
,beforeSend: function() {
if(isWatingForResponse) {
return false;
}
isWatingForResponse = true;
}
,complete: function() {
isWatingForResponse = false;
}
,success: function (data) {
//process data
}
});
Or follow #qw3n answer. This should work with jQuery 1.4.2
As I see the OP question:
How to set up fault-tolerance on the client-side because of Db-server issues, using jQuery Ajax?
This IMHO, is a really good question.
If I may, I would like to map out the pipe:
web-client->network->web-server->network->Db-server
Db-server->network->web-server->network->web-client
Your solution to this problem of handling issues with the db-server in the client is workable, but really does not address the actual problem. It could really cripple you for future extension of your client.
You should really be handling this issue as close to the problem as possible. In the web-server.

Categories