I have a long running process that takes about 13-15 minutes to finish. The problem is that, the "complete" and "success" events are never executed. I can confirm from back end that the process has finished (can see updated time stamps in sql table), but on front end, the loading icon keeps spinning.
When I check the Network tab in IE Developer Tools, that specific request remains in "pending" state forever. Interestingly, if I run the same process in Firefox, it correctly execute the complete and success events.
Here is the code (pretty standard post request):
$.ajax({
type: "POST",
url: url,
data: JSON.stringify(params),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
beforeSend: function () {
//Do something
},
complete: function () {
$('#overlay').hide();
},
success: function (retMessage) {
//reload page data
},
error: function () {
}
});
Please help, thanks.
Related
I'm building a website using Laravel and Jquery. The page is issuing multiple AJAX calls.
One of these calls can take multiple seconds and it seems to be blocking other elements of the page from loading. This includes images and other AJAX calls.
My code more or less looks like this.
$.ajax({
async: true,
url: url,
data: {
//data
},
success: function (response) {
//Process response (append html, images, etc.)
for (var key in response) {
newAJAXCall(response[key]);
}
},
error: function (xhr) {
}
});
newAJAXCall call looks like this:
$.ajax({
async: true,
url: url,
data: {
//data
},
success: function (response) {
//Process response
},
error: function (xhr) {
}
});
newAJAXCall is what's causing the problem. Some of the calls are done within 200 ms. but some can take multiple seconds. When this happens, if any elements didn't load yet they stop loading.
In the case of images, the html for them is already existing. The browser just stops loading them until the AJAX call is done.
I already tried setting async and using a timeout but nothing seems to fix it. The problem happens both in Chrome and Safari so it doesn't seem to be browser specific.
EDIT: Even when the for-loop is removed and the new ajax call is only issued once the problem persists if the call lasts long.
EDIT2: Could it be possible that Laravel/Php is limiting the amount of connections a single client can open?
EDIT3: It seems to be my server which causes the problem. When I load the images from a different server than my own they load fine during the ajax requests.
The problem was that my localhost server didn't have enough capacity. When the website runs on my dedicated server everything loads fine.
As per my comment, please consider putting for loop within newAJAXCall success function
$.ajax({
async: true,
url: url,
data: {
//data
},
success: function (response) {
//Process response (append html, images, etc.)
newAJAXCall(response);
},
error: function (xhr) {
}
});
function newAJAXCall(response) {
$.ajax({
async: true,
url: url,
data: {
//data
},
success: function (response) {
for (var key in response) {
//Process response[key]
}
},
error: function (xhr) {
}
});
}
I have requirement to manage 2 AJAX jQuery functions to start a process in the server and get the status from the server.
I,e. The first AJAX JQuery which will send a request to the server to start a particular process and returns back to the client with the status 'process-running'. The second AJAX JQuery function which will be called inside the success block of first function and its responsibility to query the status until it gets the response 'process-complete'.
Here is the psedo code I have
//This function which will be called on a button click
function buildApplication(){
//show the gif spinner in the front-end
$.when(buildApp()).then(function(result){
console.log('process-completed');
//hide the gif spinner in the front-end
});
}
function buildApp(){
return $.ajax({
type: 'POST',
url: 'url pointing to php script',
data: dataString,
cache: false,
success: function(result){
if(result == 'process-running'){
console.log('monitor starts');
getAppStatus();
console.log('monitor ends');
}
},
error: function(result){
}
});
}
function getAppStatus(){
console.log('Querying server');
return $.ajax({
type: 'POST',
url: 'url pointing to php script',
data: dataString,
cache: false,
success: function(result){
if(result == 'process-running'){
getAppStatus();
}
},
error: function(result){
}
});
}
The sleeping process is handled inside the PHP script of getAppStatus. I.e, If process is still running then the server will sleep for 10 seconds and then only returns response to the client.
The problem is both the functions are running asynchronous. That means the buildApp function invokes the getAppStatus function and just returns back immediately. The getAppStatus function runs as an orphan process.
How can I make it both synchronous (or similar) so that the parent caller will wait till the child to return back?
Note: I tried the async:false in the getAppStatus function but it freezes the browser and the ajax loader image stops spinning and it looks like hanged.
I know this has been asked, probably, a million times, but for the life of me I cannot get anything to work.
I have a UI wizard control that on the "changed" event validates the model. If the model is not valid, it doe not allow the user to move forward in the wizard. I have tired using the $.when().done() feature in jquery, but my code still passes through before making sure the model is valid. The reason for calling an async ajax request is I do not want the UI to lock up so I can show some sort of progress indicator. I had set the async property to false, but my UI indicator would never show up. Here is an example of what my code is doing:
//the change event that is called when the user clicks 'next' on the wizard:
wizard.on('change', function (e, data) {
var isValid = $.validate({
"Model": [The_UI_MODEL],
"Url": [URL_To_Server_Validation],
"Async": true, //tells ajax request to send as async
});
//Tells the wizard not to move 'next' if the request comes back as not valid
if (data.direction === 'next' && !isValid) {
e.preventDefault();
}
}
//I am using the $.extend method for JQuery to create a function that will validate any model in my system.
validate: function(options) {
//Clear any previous validation errors
$.clearValidations();
var data = $.postJson(options);
//the result is getting returned before the $.postJson(options) finishes
return data.Success;
}
//I created my own method that extends the $.ajax method so I could do other things before /after a request:
postJson: function(options){
...other code for my application
//This is where I want the ajax request to happen and once done return the data coming back
//This is what I have tried, but it is not doing what I thought.
$.when(function(){
return $.ajax({
url: options.Url,
type: 'POST',
cache: false,
async: options.Async,
timeout: options.Timeout,
contentType: 'application/json; charset=utf-8',
dataType: "json",
data: JSON.stringify(options.Model),
error: function(xhr, status, error) {
...do stuff if ajax errors out
},
success: function (data) {
},
});
}).done(function(response){
//looks like i get back the responseText of the request. which is fine, but other posts i have read stated i should be getting back the request itself
...other UI stuff
return response;
})
}
KarelG is absolutely right. You need to refactor your code and do your valdiation check within the success callback of the ajax request.
Something like this...
wizard.on('change', function (e, data) {
$.ajax({
url: [URL_To_Server_Validation],
type: 'POST',
cache: false,
async: true,
contentType: 'application/json; charset=utf-8',
dataType: "json",
data: {"Model": [The_UI_MODEL]},
success: function (response) {
//Tells the wizard not to move 'next' if the request comes back as not valid
if(!response & data.direction === 'next')
{
e.preventDefault();
}
}
});
});
It looks like you're trying to write asynchronous code as if it were synchronous. An asynchronous call such as your $.validate() will return immediately without a result and continue on to the rest of your code. Anything you want to happen when the validate call finishes must be done in a callback function passed to it.
You can use jQuery promises (when, then, done, etc.) or another library such as async.js to help manage the control flow.
Also, this isn't particularly useful now since there's little to no browser support for it yet, but the yield operator plus a library such as Task.js will eventually let us write asynchronous code as if it were synchronous.
I have a button click event that initiates an ajax call, and I need the ajax call to be synchronous so I set async:false. I want to provide feedback to the user so they know that the ajax call is happening in the back. So I have the following:
$('#ajaxBtn').on("click",function() {
$('#ajaxBtn').html("processing ...");
$.ajax({
type: "Get",
url: "example.php?data=test",
async: false,
success: function(){
alert("success");
},
error: function(){
alert("failure");
}
})
}
On Chrome (haven't tested on other browsers) When I click the button, everything freezes while the ajax call completes, however the text on the button doesn't update until the success alert pops up. If I step through the code in the debugger it works as I would expect. The text on the button changes before the ajax call initiates.
If I set Async: true it also seems to work as expected. The text changes immediately and then I get to the success function.
Is Chrome reordering the ajax call to happen before the changing of the text? Why am I seeing this?
What about something like this.
$('#ajaxBtn').on("click",function() {
$.ajax({
type: "Get",
url: "example.php?data=test",
//note that I have removed the async: "false",
beforeSend:function(){
$('#ajaxBtn').html("processing ...");
},
success: function(){
alert("success");
},
error: function(){
alert("failure");
}
}).done(function(data){
//submit your form here depending on which data is returned
});
}
I am sure this has been discussed repeatedly, but I am stumped. I am using jQuery to make an AJAX call to an ASP.NET Web service which returns some HTML. That part is working fine.
I want to do some calculations on the height of the HTML returned, but when the the call happens for the first time I am getting a height of 0. I know my calculation are just happening before the AJAX call is complete, because on the second attempt it works. If I clear cache then it returns 0 again.
I need to fire an event after the html is rendered. I have tried both global and local events like ajaxComplete.
$.ajax({
type: "POST",
url: "Webservices/Service.asmx/HelloWorld",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#OverlayContent").html(msg.d);
}
complete: function(msg) {
alert($("#OverlayContent").height());
}
});
I appreciate any help.
Sounds like your height calculation is running before the html is inserted and rendered in the DOM. Make sure to stagger it with a setTimeout call or an interval. For example:
$.ajax({
type: "POST",
url: "Webservices/Service.asmx/HelloWorld",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#OverlayContent").html(msg.d);
setTimeout(function(){ getHeight();},100);
}
});
function getHeight(){
// If our height is 0, set a new timeout and we'll check again
if($("#OverlayContent").height() === 0){
setTimeout(function(){ getHeight() }, 100);
}
else{
alert("The height is: " + $("#OverlayContent").height());
}
}
You need to poll on the html being inserted into the DOM and rendered.
In all likelihood the complete event is firing simultaneously if not before the success event, since complete fires as soon as the AJAX data is finished being received. The success event is fired once it receives return data with the 200 OK status code.
You could use a delay, but personally I think using jQuery's queue() method would be better:
success: function(msg) {
$("#OverlayContent").html(msg.d).queue(function(){
alert($("#OverlayContent").height());
$(this).dequeue();
})
}
The dequeue() at the end there is important to restore the normal flow of things.
At that point you just get rid of the complete callback entirely.
I may not be understanding your question entirely, but you could try setting the update code in an timeout that runs immediately after the completed event...
//..your other code here
complete:function(m) {
setTimeout(function() {
alert($("#OverlayContent").height());
},1);
}
//...the rest of your code