Here are the two ways of implementation, that describe the issue.
The first one is the method that works really slow. It tries to get data from server, but the request is pending too long, only after that it returns data and everything's fine (except the terrible synchronous perfomance).
asyncMethod: function(doSmth, param) {
var resp = $.ajax({
type: 'GET',
async: false,
url: 'url'
});
data = resp.responseText;
doSmth(param, data);
}
Here is the same method, but it's asynchronous. The perfomance problem is eliminated here. But it executes the part in success only when page is reloaded. Probably reload stops some executions that were the bottleneck of the previous code sample.
asyncMethod: function(doSmth, param) {
var resp = $.ajax({
type: 'GET',
url: 'url',
success: function () {
data = resp.responseText;
doSmth(param, data);
}
});
}
I don't need to use asynchronous request, if the synchronous one works fast (but now it doesn't). There seem to be some executions, that make the request remain pending for too long. I don't see the execution that may be a bottleneck. Maybe it's somewhere in the libraries that are used, but no other requests are active when resp is being processed.
What are the ways to fix the problem or to analyze it? An advice would be appreciated.
There are two main culprits if a response is sat on "pending" for too long:
The application code that is fulfulling the ajax request is taking longer than expected
Simple network latency (not much that can be done about that in the application layer)
If you have access to the code that is fulfilling the request then I'd start there. Also, it's probably not a network issue if this request is taking an unusually long time compared to all your other requests
Have you tried the async method like this:
asyncMethod: function(doSmth, param) {
$.ajax({
type: 'GET',
url: 'url',
success: function (response, status) {
doSmth(param, response.responseText);
}
});
}
Related
I have an ajax request that may take a long time to return a response.
$.ajax({
type: 'POST',
url: 'some_url',
data: data,
processData: false,
contentType: false,
headers: {
"Authorization": 'Token token="'+some_token+'"'
}
}).then(function(){
do_something();
});
If the request takes a few minutes then everything works as expected. But if the response takes more than about 10 minutes; I get the following error:
jquery.js:9175 POST 'some_url' net::ERR_EMPTY_RESPONSE
But on the server, I can still see that my request is being processed. When that process is finished, I can see that it sends a Completed 201 Created ... response. But I believe since the error is encountered there is nothing listening for the response.
I would like to let the user know the process is finished.
Does any one know the 'best practice' way of handling this?
Any help would be greatly appreciated.
Since Ajax is assynchonized, I like to apply a promise. From the top of my head i believe this works like follows:
function send_ajax(url, data, some_token) {
var ajax = $.ajax({
type : 'POST',
url : url,
data : data,
processData : false,
contentType : false,
headers : {
"Authorization" : 'Token token="' + some_token + '"'
}
})
return ajax.promise();
}
send_ajax("url","data","some_token").done(function(result) {
console.log(result);
do_something();
});
The result is promised and when returns will execute the function inside done. 10 minutes does seem like an awful long time.
edit: not the solution
As I was pointed out the original Ajax call stays within its context. Meaning that the then() method will handle the returned call. My opted solution does not apply to the OP problem.
For reference, the opted solution does handle the asynchronous hurdle when the ajax logic is placed in its own function with a returned value.
Is there a way to confirm whether a particular ajax request in async or sync in Browser Dev Tools like Chrome Developer Tools or Firebug.
For ajax request HTTP Request Header does not indicate whether its sync or async.
X-Requested-With:XMLHttpRequest
no you cant do that but you can run this in console or add this to your code
XMLHttpRequest.prototype.open = (function(open){
return function(method, url, async, user, password) {
console.log("xhr call: "+url +"isAsync: "+async);
open.apply(this, arguments);
};
})(XMLHttpRequest.prototype.open);
it logs the infomation :D hope its helpful
I don't know if you are still looking for an answer but I hope this will help someone!
In chrome browser navigate to rightClick/inspect/networkTab/xhr? move the cursor to the time where your requests are processed as shown in below pic:
THIS IS MY ASYNC CODE(default ajax)
`$.ajax({
type: "GET",
contentType: "application/json", // data type of request
url: //url,
data: //data,
dataType: "json", // data type of response
success: function (result) {
// some code here
}
});`
I was making a series of ajax calls to the localhost and each call was linked to the previous call's response. But I got wrong outputs because all the ajax requests were being sent at almost the same time and the responses(blue in color) which should have been received serially were disordered. The timing diagram below shows the issue perfectly(look at the waterfall tab).
THIS IS MY CODE FOR SYNC CALLS(async: false in ajax)
$.ajax({
async: false,
type: "GET",
contentType: "application/json", // data type of request
url: //url,
data: //data,
dataType: "json", // data type of response
success: function (result) {
// some code here
}
});
Now how to know if async: false is working?
You can see that the timings of ajax calls in async mode are overlapping each other and also the timings for calls in sync mode(async: false) are distinctively separate thus proving that sync calls [async: false] are working fine. If the timings still overlap then sync calls are likely not working, unlike my case.
All ajax requests are asynchronous others wise if its specified to be synchronous hence why they call it Asynchronous JavaScript and XML (AJAX). To make an ajax request synchronous you would have to pass in false inside the open method of an XMLHTTPRequest object like this
var xhr = new XMLHttPRequest();
xhr.open("POST", "file to get.php", false);
The third parameter specifies it as synchronous but it defaults to true
If I use Ajax to send request and this request take long time ..... if I want to send anther request what should I do?
the current behaviour the second request (I did) waiting until the first request get with response.
NOTE :
i want to do this behaviour on whole application (any new request execute immediately not wait the old one to be finished firstly)
My application using (Ajax + PHP + jQuery + Symfony)
Assume that is the first request take long time:
$.ajax
({
type: "GET",
url: url1,
success: function (html)
{
// do some thing
}
});
In any time I want this request to execute and terminate the first one.
$.ajax
({
type: "POST",
url: url,
success: function (html)
{
// do some thing else
}
});
var xhrReq;
xhrReq = $.ajax(...);
// then if you want to stop the rqest and exit use :
xhrReq.abort();
It’s sort of a manual process, but you can add a global xhr object and test it on each request. If the readystate is "loading", abort it:
var xhr;
var loadUrl = function(url) {
if ( xhr && xhr.readyState > 0 && xhr.readyState < 4 ) {
// there is a request in the pipe, abort
xhr.abort();
}
xhr = $.get(url, function() {
console.log('success', this);
});
};
loadUrl('/ajax/');
The XMLHttpRequest object has an abort function. You can use setTimeout to abort a request that is taking too long.
EDIT: In the case you do not want to use a timer, and a new event occurs that should abort the prior request, then the event handler should do the following
if(!this.request) return; // request contains the XMLHttpRequest
this.request.onreadystatechange = function() {};
if(this.request.readyState != 4) {
this.request.abort();
}
Then after that you can create the new XMLHttpRequest object.
I have been working on this many ways and I feel I found a working solution. I had a caching process that was causing a page to hang until done (average 5 seconds). Yes this is better suited as a CRON job, but I needed to create caching process for the user without knowing the environment they are using for my CMS.
What I had done:
Create the call within a variable and then remove it by a hard delete. By deleting this it seems to be removing the wait. This "hack" seemed to pull the wait from 5 second average to a 325ms wait.
var ignore = $.ajax({
url:something/here.php,
type: "GET",
url: url1,
success: function(){}
});
delete ignore;
Defining the ajax request variable:
var xhr;
Making the ajax call:
xhr = $.ajax(...);
Aborting the ajax call:
xhr.abort();
Browser allows you to handle only limited amount of requests to same host at time (2 or 3 as I remember, depending on browser).
Workaround on requests count is to make fake domains - like img1.domain.com, img2.domain.com, etc. leading to the same host and randomly use them in requests. Then you can just make requests you need. Domains count should be chosen depending on requests quantity in order to keep in bounds - 2 requests per domain. Otherwise 3rd request will wait until one of active finishes.
It allows you to receive responses from all your requests.
For example, Google uses it to make images load faster.
EDIT:
Example: you have http://yourhost.com/ and alias http://alias.yourhost.com which points to the same place.
Then:
$.ajax
({
type: "GET",
url: 'http://yourhost.com/somescript.php',
success: function (html)
{
// do some thing
}
});
and then
$.ajax
({
type: "POST",
url: 'http://alias.yourhost.com/somescript2.php',
success: function (html)
{
// do some thing else
}
});
I have an ajax application, which has code something like this:
$.ajax({
type: "GET",
url: "data.txt",
beforeSend:function(){
},
success:function(response){
just update responsed data;
}
});
this call is made every second and it just updates the latest data from 'data.txt' which is being updated on server using cron job. Now since it's only function is to update latest data each second so I'll be more interested in the latest ajax call ; so how can I terminate old ajax call that has crossed 4 seconds but yet not completed so that I can reduce the server traffic. And any suggestion if using 'data.html' or 'data.php' instead of 'data.txt' would increase the application performance ? And which web server can perform better than Apache for ajax driven application ? I need these help urgently ; Please do help.
You could keep track of when your last successful update time was.
function NowMS() {return parseInt(new Date().getTime())}
dataLastUpdateT = -Infinity;
$.ajax({
type: "GET",
url: "data.txt",
success: function(response){
if (NowMS() > dataLastUpdateT) {
use(response);
dataLastUpdateT = NowMS();
}
}
}
I don't know how you have it setup at the moment but perhaps it would be better to run your next AJAX call after the latest one completed (or returned an error). So it would be something like:
(function updateData() {
$.ajax({
type: 'GET',
url: 'data.txt',
beforeSend: function() {
// Do stuff
},
success: function(response) {
// Handle response
updateData();
}
});
})();
I don't know if there is any performance changes in changing the file type.
Edit: If you do need to just kill the request, you can do so using the technique explained here.
You could try this:
function getData(){
$.ajax({
type: "GET",
url: "data.txt",
timeout:4000,
beforeSend:function(){
},
success:function(response){
},
error:function(){
},
complete:function() {
setTimeout(function(){getData();},1000);
}
});
}
getData();
this way the ajax request timeouts after 4 seconds and retries each second (regardless of success or timeout)
Also have a look at nginx for example, it is fast and uses less memory than apache to handle client connections
I'm developing a javascript application and I'm trying to make server side syncing as automagic and unobtrusive as possible
The problem I'm facing is that when creating an object client side I can immediately send the create ajax request and while I'm waiting for it to return add the object to the ui where necessary
However since the object has no id until the server responds I can't perform any update or destroy actions on it until the server responds and updates its id
What is the best way of dealing with this problem?
Some code if it helps:
create_object = function() {
return {
save: function() {
if (this.isNew()) {
this.create();
} else {
this.update();
}
},
isNew: function() {
return (this.id === undefined || this.id === null);
},
update: function () {
$.ajax({
url: '/update_object/'+this.id+'.json',
type: 'post',
dataType: 'json',
data: this
});
},
create: function () {
var object = this;
$.ajax({
url: '/create_object',
type: 'post',
dataType: 'json',
data: this,
success: function(data) {
object.id = data.id;
}
});
},
destory: function () {
$.ajax({
url: '/destroy_object/'+this.id+'.json',
type: 'get',
dataType: 'json'
});
}
};
};
var object = create_object();
object.message = "Foo!";
object.save();
// this will create a new object until object.save has responded
object.message = "Bar!";
object.save();
// this wont work until object.save has responded
object.destroy();
This is not really a problem. AJAX is asynchronous by nature (Asynchronous Javascript and XML). You will have to wait until you get a response from the server to update your UI.
If you must update the UI immediately, you can create an element with a placeholder ID that you can then update with the actual ID once the server responds.
UPDATE
This is in response to your comment. Webapps are not purely client-side applications. They fit into the client-server paradigm. You can try using a synchronous post, but this has the side-effect of tying up the browser until the server responds (this is due to the fact that Javascript is single-threaded).
That being said, the response from the server should be pretty quick unless your network is slow or if whatever post your sending to the server results in some computationally-intensive operation.
Going by the placeholder route will (as you have realized) result in all sorts of new problems that you have to deal with. You have to ensure that they are unique. Now what if they perform some operation on the client-side element before the server responds with an id? The server won't know what the placeholder id means. There are ways around this (queuing requests is one way), but it will make your code a whole lot more complicated. I don't think the tradeoff is worth it just to make the UI update faster.
An option is to provide some visual feedback to the user that the app is "working" (i.e., while you are waiting for a response from the server). A spinner, for example.
As far as stacking the AJAX requests, that is one approach that you can take using the jQuery message-queuing plugin.