I have an ajax request as following,
$.ajax({
url: scriptUrl,
dataType: 'script',
timeout: 6000,
cache: true,
success: function() {
some code
},
error: function(jqXHR, textStatus, errorThrown) {
some code
}
});
I use this to get branding template. & this template may or may not exist.
The problem is if it fails, i get the response in about 200ms, but my error callback gets invoked after 6sec or what ever time is set in the timeout.
But if the request is successfull, then it goes to the success callback as soon as the response is given. If I remove the timeout, none of the success or error callback gets executed.
The request is made to a CDN, & if the file doesn't exist on the server it returns a status code of 403.
My question is, How can i execute the error callback upon arrival of the response regardless of what ever timeout is set?
Thanks you in advance.
Related
Send through ajax each element from the following array. Note: Each request must
be made once the previous has finished.
[‘This’, ‘is’, ‘a’, ‘fake, ‘array’]
I am a little confused by this question because I thought Ajax is asynchronous, meaning the script keeps sending requests to the server without waiting for the reply.
***Was downvoted so going to clarify something: It specifically states in the problem statement that the REQUEST must be made synchronously. I do realize that there are better ways of doing this via def/promises asynchronously so order remains for the result but that isn't the request.
Ajax has a async parameter you can set to false which will block until call completion.
Per documentation:
async (default: true)
Type: Boolean
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done().
http://api.jquery.com/jquery.ajax/
Example:
$.each(["This", "is", "a", "fake", "array"], function( index, value ) {
$.ajax({
type: 'POST',
dataType: 'json',
url: '/echo/json/',
data : { json: JSON.stringify( value ) },
async: false,
success: function(data) { alert(data);}
});
});
Working fiddler example: https://jsfiddle.net/zm9bb4xk/
I was talking about JQuery Ajax.
So, first, based on documentation, Ajax has many events that run at certain times, for example:
beforeSend (Local Event)
This event, which is triggered before an Ajax request is started,
allows you to modify the XMLHttpRequest object (setting additional
headers, if need be.)
error (Local Event)
This event is only called if an error occurred with the request (you
can never have both an error and a success callback with a request).
complete (Local Event)
This event is called regardless of if the request was successful, or
not. You will always receive a complete callback, even for synchronous
requests.
success (Local Event)
This event is only called if the request was successful (no errors
from the server, no errors with the data).
More in documentation.
Second, following your example (you have to complete this with your own data and this code is not tested, maybe it has some small sintax errors), an approximation is:
// Variables
var myArray = ["This", "is", "a", "fake", "array"];
var globalIndex = 0;
// Function for Ajax Calls
function myFunction(){
$.ajax({
url: 'myURL', // Your own controller/url
type: "GET", // Or POST
dataType: "json", // Or other datatype
data: {
arrayContent: myArray[globalIndex] // arrayContent = your controller param name
},
/**
* A function to be called if the request succeeds.
*/
success: function(data) {
alert('Load was performed. Look at the console (F12 or Ctrl+Shift+I, Console tab) for more information! ');
alert(data); // Do what you want with your data, this is an example
globalIndex = globalIndex +1;
// Recursive/next call if current call is finished OK and there are elements
if(globalIndex < myArray.length){
myFunction();
}
},
/**
* A function to be called if the request fails.
*/
error: function(jqXHR, textStatus, errorThrown) {
alert('An error occurred... Look at the console (F12 or Ctrl+Shift+I, Console tab) for more information!');
alert('<p>status code: '+jqXHR.status+'</p><p>errorThrown: ' + errorThrown + '</p><p>jqXHR.responseText:</p><div>'+jqXHR.responseText + '</div>');
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
// We don't do a recursive/next call because current call has failed
},
});
}
// First call to myFunction
myFunction();
I'm utilizing the magic of jQuery.ajax( settings ).
However, I'm wondering if anyone has played with the timeout setting much?
I know it's basically for dictating the local time for a request, but can it trigger anything if the timeout is reached? Or does it simply stop listening for a response?
Reading the jQuery site, I can see there are no arguments passed, so it seems like a simple setting with one capability. Which is fine.
But, I'd like to trigger an alert or some function if the timeout is reached. I can see that the error setting doesn't get triggered, in this case.
Here's my snippet:
$("form#testform").submit(function(){
var allFormValues = $("form#testform").serialize();
$.ajax({
cache:false,
timeout:8000, // I chose 8 secs for kicks
type:"POST",
url:"someurl.php",
data:allFormValues,
error:function(){ alert("some error occurred") },
success:function(response){ alert(response); }
});
});
Does anyone know how to work more with timeout?
If your error event handler takes the three arguments (xmlhttprequest, textstatus, and message) when a timeout happens, the status arg will be 'timeout'.
Per the jQuery documentation:
Possible values for the second
argument (besides null) are "timeout",
"error", "notmodified" and
"parsererror".
You can handle your error accordingly then.
I created this fiddle that demonstrates this.
$.ajax({
url: "/ajax_json_echo/",
type: "GET",
dataType: "json",
timeout: 1000,
success: function(response) { alert(response); },
error: function(xmlhttprequest, textstatus, message) {
if(textstatus==="timeout") {
alert("got timeout");
} else {
alert(textstatus);
}
}
});
With jsFiddle, you can test ajax calls -- it will wait 2 seconds before responding. I put the timeout setting at 1 second, so it should error out and pass back a textstatus of 'timeout' to the error handler.
Hope this helps!
I'm having a trouble with ajax requests and server responses:
$.ajax({
url: servurl,
dataType: "jsonp",
data: {... },
crossDomain: true,
error: function(){},
success: function(){},
complete: function(){alert('complete')}
});
}
The thing is - sometimes I get succes, when I should get it, but sometimes I can get 500 status, and it is normal and expected.
The same ajax call works for correct requests, but fails for others.
I want to display an error message if I get a 500 server error, but for some reason the ajax does not complete. Thus, neither error: nor complete: work.
Maybe the reason for that is 'jsonp' datatype? Other datatypes do not work though.
Can someone help please?
Or maybe give me an advice on how to detect server status any other way.
jsonp requests do not trigger error callbacks by design, therefore there is no way for you to catch the error with javascript. I suggest instead implementing an error handler on your server that detects a jsonp request and returns jsonp that indicates an error has occured rather than a 500 status code.
Note that error: is deprecated as of 1.8 and is not called for JSONP however I wonder if you might have success using the Promise functionality introduced with 1.5 for deferred http://api.jquery.com/category/deferred-object/ as:
jqXHR.fail(function(jqXHR, textStatus, errorThrown) {});
jqXHR.done(function(data, textStatus, jqXHR) {});
jqXHR.always(function(data|jqXHR, textStatus, jqXHR|errorThrown) { });
Example for your code:
$.ajax({
url: servurl,
dataType: "jsonp",
data: {... },
crossDomain: true
}).done(function(data, textStatus, jqXHR){ //replace success
alert(textStatus);
}).always(function(data|jqXHR, textStatus, jqXHR|errorThrown) { // replace complete
alert(textStatus);
}).fail(function(jqXHR, textStatus, errorThrown) { // replace error
alert(errorThrown);
});
Make sure that you are accessing to your server. Maybe you are requesting in your server for an specific contentType (like application/json) and you are not using that property into your ajax call.
As you requested, to show any message if get a error (400, 404, 500...), you can use my custom function for ajax error responses:
function onErrorFunc(jqXHR, status, errorText) {
alert('Status code: ' + jqXHR.status + '\nStatus text: ' + status +
'\nError thrown: ' + errorText);
}
Usage:
$.ajax({
//some options
error: onErrorFunc
});
Please, show us what error thrown your server.
Thank you all for comments. Jquery .ajax really does not give errors on jsonp requests.
The way to get error messages was to implement the jquery-jsonp plugin:
https://github.com/jaubourg/jquery-jsonp
The javascript below accomplishes the following (this is for a node.js COMET application):
Request is made to the server and held until the server has something to
return.
Once the request returns the data is processed and another
request is immediately made within the callback function of the
success event.
If a timeout occurs (the server had nothing to return within the time frame)
another request is made within the callback function of the error event.
My concern (which I believe is valid) is that the requests are continually added to the callstack, much like a recursive function that never ends. After a while, it results in the browser eventually crashing and becoming unresponsive (at least I think this is the cause).
How can I accomplish the same thing and avoid this problem?
function GetData(){
$.ajax({
url: "admin.html",
type: "POST",
dataType: "json",
contentType: 'text/json',
data: JSON.stringify({
cmd: "getData"
}),
timeout: (60 * 1000),
success: function(data, textStatus, jqXHR){
UpdateScreen(data);
GetData();
},
error: function(jqXHR, textStatus, errorThrown){
if(textStatus == "timeout"){
GetData();
}
}
});
}
No, I'm pretty sure you are OK. The ajax event is asynchronous, so the GetData function will finish and the browser will wait for events, before it calls GetData again from the success handler.
Think of it as the GetData function just defining what to do, not actually doing it. Then it finishes executing (and clears the stack) and browser does those actions.
function GetData(limit){
limit = limit || 0;
$.ajax({
url: "admin.html",
type: "POST",
dataType: "json",
contentType: 'text/json',
data: JSON.stringify({
cmd: "getData"
}),
timeout: (60 * 1000),
success: function(data, textStatus, jqXHR){
UpdateScreen(data);
GetData();
},
error: function(jqXHR, textStatus, errorThrown){
if(textStatus === "timeout" && limit < 20){
GetData(++limit);
} else {
//throw "epic fail"
setTimeout(GetData, 0);
}
}
});
}
Just add a little timeout limit counter. if it gets too big either give up and throw an error or break the call stack by calling setTimeout which is asynchronous.
I'm wondering if your UpdateScreen(data) method is the problem. Is that a recursive function as well? People suggesting that you simply timeout the method doesn't actually fix the problem, it simply aborts the process. I would try logging something like console.log("get data success") and console.log("get data error") in your success and error callbacks respectively. If your log page is full of one message, you know where the GetData() method is continually called. It could be always timing out.
On a side note, you should change your if statement for an error to something like
if(jqxhr.responseText == "timeout"){
getData();
}
see here for explanation why: jQuery Ajax error handling, show custom exception messages
A little background:
I am trying to implement and AJAX powered SlickGrid. There isn't much documentation so I used this example as a base.
In this example there is the following code that hits the desired web service to get the data:
req = $.jsonp({
url: url,
callbackParameter: "callback",
cache: true, // Digg doesn't accept the autogenerated cachebuster param
success: onSuccess,
error: function(){
onError(fromPage, toPage)
}
});
req.fromPage = fromPage;
req.toPage = toPage;
I'm not exactly sure what jsonp does but from what i've read it appears to be very similar to the ajax method in jQuery except it returns json and allows cross domain requests. The webservice that I happen to be calling only returns XML so I changed this chunk of code to:
req = $.ajax({
url: "/_vti_bin/lists.asmx",
type: "POST",
dataType: "xml",
data: xmlData,
complete: onSuccess,
error: function (xhr, ajaxOptions, thrownError) {
alert("error: " + xhr.statusText);
alert(thrownError);
},
contentType: "text/xml; charset=\"utf-8\""
});
req.fromPage = fromPage;
req.toPage = toPage;
My issue is that my page errors out at req.fromPage = fromPage; because req is null.
Am I wrong to think that I can just replace my jsonp call with a call to the ajax method? Is req just not set because my ajax call hasn't finished by the time that code is executed? How can I get around either of these issues?
If I comment out the last two lines and hard-code those values elsewhere everything runs fine.
Am I wrong to think that I can just replace my jsonp call with a call to the ajax method?
No, that should work just fine.
Is req just not set because my ajax call hasn't finished by the time that code is executed?
Yes, that is correct.
The ajax methods starts the request and returns immediately. If you want to do something after the response has arrived you should do that in the success event handler.
You might actually want to use the success event instead of the complete event, as the complete event happens even if there is an error.
You could specify async: false, in your settings to make the ajax call wait for the response, but that means that the browser freezes while it's waiting.
As Guffa stated, $.ajax() works asynchronically. Thus, you have to specify a callback that will be called when the request has returned a response, rather than to just use whatever $.ajax() returns.
There are a couple of different callback methods you can specify:
complete - runs when you recieve a response, regardless of its status.
success - runs when you recieve a response with a successful status code (usually 200).
error - runs when you recieve a response with an error code (for example 404 or 500).
To do something with the response body after a successful request, you should do something like
$.ajax({
...
success: function(body) {
alert('This is the method body:' + body);
}
});
Read up in the documentation on the different methods to see what more parameters you can use.