No error handling in jQuery AJAX call invoked - javascript

I'm trying to make the AJAX call bark and squick at me so I'm executing a totally wrong URL. For some reason, none of the methods that are supposed to do the barking och squicking is invoked.
What is the reason?
$.ajax({
url: "http://totally.wrong.url",
dataType: 'jsonp',
error: function () { alert("bark 1"); },
failure: function () { alert("bark 2"); }
})
.fail(function () { alert("squick"); })
.done(function () { alert("woof"); });
Of course, if I change the URL to point to the correct WCF service, I get an approving woof.
According to jQuery API, I should use fail and done syntax but I'll be fine either way.
Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are deprecated as of jQuery 1.8. To prepare your code for their eventual removal, use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.

Ajax with JSONP and Cross Site Requests won't trigger the error callback.
Look at the accepted answer in this question: jQuery Ajax 404 Handling
Hopefully this should explain what you need to make it work.

I don't know if failure is supposed to work but I always use "error" and "success" instead.
So try:
$.ajax({
url: "http://totally.wrong.url",
dataType: 'jsonp',
error: function () { alert("bark");},
success: function () { alert("woof");}
}
})

$.ajax({
url: "http://totally.wrong.url",
dataType: 'jsonp',
**error**: function () { alert("bark"); }
})
.fail(function () { alert("squick"); })
.done(function () { alert("woof"); });
error is the request fail callback function and not failure

Related

Syncronous AJAX stops on Error

I do have AJAX request and in the success callback new function to rendergooglelinks and another AJAX calls are called.
And now, I try to change the asyncronous calls to syncronous using async: false in the AJAX request.
When I do a AJAX request, rendergooglelinks are not rendered due to "undefined" error and next ajax request works.
In the syncronous ajax request, progress stops after rendergooglelinks error. Next calls are not triggered.
(i.e) Codes after that error are not processed.
Whether syncronous ajax request stops on errors ?
Whether it behaves in the way of "strict" mode ?
How can we handle this ?
// syncronous request
$.ajax({
type:"GET",
async: false,
url: url,
success: function(result, status, xhr) {
rendergooglelinks();
renderComments(); // this is not called due to error in the above
}
});
function rendergooglelinks()
{
google.test = ''; // returns error
}
function renderComments()
{
// asyncronous request
$.ajax({
type:"GET",
url: url,
success: function(result, status, xhr) {
}
}
});
Based on the code you posted, the error is that the variable google is never declared, so google.test cannot be assigned.
On the other hand, synchronous ajax calls are not a good practice, avoid them if possible.
Last but not last from jQuery.ajax() docs:
Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are removed as of jQuery 3.0. You can use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.
For the google variable, i suggest you to pass it to the function as argument, is dangerous to assume that it exist no matter what.
For other errors, try this:
$.ajax({
type:"GET",
//async: false,
url: url,
/*success: function(result, status, xhr) {
rendergooglelinks();
renderComments(); // this is not called due to error in the above
}*/
}).then([ //success callbacks
rendergooglelinks,
renderComments
],[
//no fail callbacks
]);
function rendergooglelinks(){
google.test = ''; // returns error
}
function renderComments(){
// asyncronous request
$.ajax({
type:"GET"
url: url,
/*success: function(result, status, xhr) {
}*/
}).done(function(result, status, xhr){
});
}
See also jQuery Deferred

Async AJAX call not working with when and then

I have the following code:
function accessControl(userId) {
return $.ajax({
url: "userwidgets",
type: "get",
dataType: 'json',
data: {
userid: userId
}
});
};
var userWidgets = accessControl('1');
$.when(userWidgets).then(function (data) {
alert(data);
});
I don't want to make the function sync by adding the parameter async: false, but the alert isn't appearing at all, is there something wrong in my code? should I use another approach?
$.ajax returns a promise. So, it don't need to be wrapped in $.when again.
Use then directly on userWidgets as it is ajax instance.
userWidgets.then(function (data) {
alert(data);
}, function(e, status, error) {
console.log(error);
// For debugging
});
From jQuery Docs
jqXHR.then(function( data, textStatus, jqXHR ) {}, function( jqXHR, textStatus, errorThrown ) {});
Incorporates the functionality of the .done() and .fail() methods, allowing (as of jQuery 1.8) the underlying Promise to be manipulated. Refer to deferred.then() for implementation details.
I don't want to make the function sync by adding the parameter async: false, but the alert isn't appearing at all, is there something wrong in my code? should I use another approach?
Making the ajax call synchronous will not solve this problem. Your approach is fine.
As #Tushar has said in his answer you don't really need to use $.when since the $.ajaxcall returns a promise so you can chain .then callbacks onto it without using $.when. But this is not the reason why your .then callback is not being invoked.
The reason why your .then callback is not being called is because that ajax call is failing and the promise is being rejected. .then callbacks are only called when promises are resolved successfully, this fiddle verifies this statement.
You will need add failure logic to your code to handle failures in your ajax call like this:
var userWidgets = accessControl('1');
$.when(userWidgets).then(function (data) {
alert(data);
})
.fail(function(){
alert("should do something on failure");
});

JQuery ajax query fails very silently

I have read similar questions with similar problems but every advice I read seems to be inefficient for me. Here is the ajax call (I am using Jquery 1.9.1):
$( document ).ajaxError(function() {
alert( "AJAX ERROR" );
});
$.post( "/lists/complete", { itemID:id }, function(answer) {
alert("SUCCESS");
}, "text" ).fail( function() {
alert("ERROR");
}).always( function() {
alert("DONE");
});
On the server side the request is received as expected. If I monitor the server response on the client side (using Firebug), I can see that the server sends the 200 response along with the correct data in the body. However, no alert is never triggered !
What can I do to understand the issue ? I must add that I have very little experience with JS and with Jquery...
I'm also not a fan of jquery post. I prefer using $.ajax. However it is recommended to chain done, fail and always.
$.ajax({
url: ' yoururl ',
type: 'POST',
// dataType: 'default: Intelligent Guess (Other values: xml, json, script, or html)',
data: {param1: 'value1'},
})
.done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
});
http://api.jquery.com/jQuery.ajax/
Deprecation Notice: The jqXHR.success(), jqXHR.error(), and
jqXHR.complete() callbacks are deprecated as of jQuery 1.8. To prepare
your code for their eventual removal, use jqXHR.done(), jqXHR.fail(),
and jqXHR.always() instead.
I v never been a fan of the $.post i rather use the full ajax call :
$.ajax({
type: 'POST',
url: '/lists/complete',
data: data,
success: function(data){
alert("SUCCESS");
},
error: function(xhr, type, exception) {
// if ajax fails display error alert
alert("ajax error response type "+type);
}
});
Give this a shot and let me know if the alerts go off.
If this doesn't work out, open up the console (firebug...) and go to the network tab, clear it and send your request.
Click on the request and check the headers and response if they are normal.

Is there any analog to a 'finally' in jQuery AJAX calls?

Is there a Java 'finally' analogue in jQuery AJAX calls? I have this code here. In my always I throw an exception, however I ALWAYS want it to go to the then() method.
call.xmlHttpReq = $.ajax({
url : url,
dataType : 'json',
type : 'GET'
}).always(function(processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {
throw "something";
}).then(function() {
alert("i want to always run no matter what");
});
I have tried to use done(), complete(), and the another always(), but nothing seems to work.
Here is JSFiddle :
http://jsfiddle.net/qv3t3L0m/
See this example:
$.ajax({
type: "GET",
dataType: dataType,
contentType: contentType,
async: TRUE,
url: $('html form:nth-child(1)').attr('action') + "?" $('html form:nth-child(1)').serialize(),
success: function(data) {
console.log("FUNFOU!");
},
error: function(data) {
console.log("NÃO FUNFOU!");
},
complete: function(data) {
console.log("SEMPRE FUNFA!");
//A function to be called when the request finishes
// (after success and error callbacks are executed).
}
});
For more informations: http://api.jquery.com/jquery.ajax/
.always() should work. See the The jqXHR Object section at http://api.jquery.com/jQuery.ajax/.
jqXHR.always(function(data|jqXHR, textStatus, jqXHR|errorThrown) { });
An alternative construct to the complete callback option, the
.always() method replaces the deprecated .complete() method.
In response to a successful request, the function's arguments are the
same as those of .done(): data, textStatus, and the jqXHR object. For
failed requests the arguments are the same as those of .fail(): the
jqXHR object, textStatus, and errorThrown. Refer to deferred.always()
for implementation details.
See also http://api.jquery.com/deferred.always/
The below suggestions will not work in jQuery, because jQuery's promise implementation does not handle errors thrown in methods passed to then. I am only leaving them here as an illustration of what could be possible if jQuery was promises/A+ compliant. As Bergi rightly points out, you will have to manually wrap your code in your own try catch block.
call.xmlHttpReq = $.ajax({
url : url,
dataType : 'json',
type : 'GET'
}).then(function(processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {
throw "something";
}).always(function() {
alert("i want to always run no matter what");
});
Although I'm not sure if jquery's promise supports always, an alternative would be to use then (again) and pass the same function as both successHandler and errorHandler, like this :
call.xmlHttpReq = $.ajax({
url : url,
dataType : 'json',
type : 'GET'
}).then(function(processedDataOrXHRWrapper, textStatus, xhrWrapperOrErrorThrown) {
throw "something";
}).then(function() {
alert("i want to always run no matter what");
},
function() {
alert("i want to always run no matter what");
});
Just a note for those who use jQuery 3.0 and later
Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are removed as of jQuery 3.0. You can use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.
As in official documentation
There is a bug ajax is dependent on the server, need to check status with "complete" is the best, a kind of "success", "error" and others are not 100% of the PUT, POST and GET ... look at an example
$.ajax({
url: '/api/v2/tickets/123456.json',
....
....
....
complete: function(data) {
if (data.statusText == "success") {
console.log("Sent successfully");
} else {
console.log("Not Sent");
}
}
});
Sorry bad english! Cheer ;-)
if you want one code definition for all ajax requests, you can do it like this
$(document).ajaxComplete(function () {
console.log('ajax complete on doc');
})

How do I verify jQuery AJAX events with Jasmine?

I am trying to use Jasmine to write some BDD specs for basic jQuery AJAX requests. I am currently using Jasmine in standalone mode (i.e. through SpecRunner.html). I have configured SpecRunner to load jquery and other .js files. Any ideas why the following doesn't work? has_returned does not become true, even thought the "yuppi!" alert shows up fine.
describe("A jQuery ajax request should be able to fetch...", function() {
it("an XML file from the filesystem", function() {
$.ajax_get_xml_request = { has_returned : false };
// initiating the AJAX request
$.ajax({ type: "GET", url: "addressbook_files/addressbookxml.xml", dataType: "xml",
success: function(xml) { alert("yuppi!"); $.ajax_get_xml_request.has_returned = true; } });
// waiting for has_returned to become true (timeout: 3s)
waitsFor(function() { $.ajax_get_xml_request.has_returned; }, "the JQuery AJAX GET to return", 3000);
// TODO: other tests might check size of XML file, whether it is valid XML
expect($.ajax_get_xml_request.has_returned).toEqual(true);
});
});
How do I test that the callback has been called? Any pointers to blogs/material related to testing async jQuery with Jasmine will be greatly appreciated.
I guess there are two types of tests you can do:
Unit tests that fake the AJAX request (using Jasmine's spies), enabling you to test all of your code that runs just before the AJAX request, and just afterwards. You can even use Jasmine to fake a response from the server. These tests would be faster - and they would not need to handle asynchronous behaviour - since there isn't any real AJAX going on.
Integration tests that perform real AJAX requests. These would need to be asynchronous.
Jasmine can help you do both kinds of tests.
Here is a sample of how you can fake the AJAX request, and then write a unit test to verify that the faked AJAX request was going to the correct URL:
it("should make an AJAX request to the correct URL", function() {
spyOn($, "ajax");
getProduct(123);
expect($.ajax.mostRecentCall.args[0]["url"]).toEqual("/products/123");
});
function getProduct(id) {
$.ajax({
type: "GET",
url: "/products/" + id,
contentType: "application/json; charset=utf-8",
dataType: "json"
});
}
For Jasmine 2.0 use instead:
expect($.ajax.calls.mostRecent().args[0]["url"]).toEqual("/products/123");
as noted in this answer
Here is a similar unit test that verifies your callback was executed, upon an AJAX request completing successfully:
it("should execute the callback function on success", function () {
spyOn($, "ajax").andCallFake(function(options) {
options.success();
});
var callback = jasmine.createSpy();
getProduct(123, callback);
expect(callback).toHaveBeenCalled();
});
function getProduct(id, callback) {
$.ajax({
type: "GET",
url: "/products/" + id,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: callback
});
}
For Jasmine 2.0 use instead:
spyOn($, "ajax").and.callFake(function(options) {
as noted in this answer
Finally, you have hinted elsewhere that you might want to write integration tests that make real AJAX requests - for integration purposes. This can be done using Jasmine's asyncronous features: waits(), waitsFor() and runs():
it("should make a real AJAX request", function () {
var callback = jasmine.createSpy();
getProduct(123, callback);
waitsFor(function() {
return callback.callCount > 0;
});
runs(function() {
expect(callback).toHaveBeenCalled();
});
});
function getProduct(id, callback) {
$.ajax({
type: "GET",
url: "data.json",
contentType: "application/json; charset=utf-8"
dataType: "json",
success: callback
});
}
Look at the jasmine-ajax project: http://github.com/pivotal/jasmine-ajax.
It's a drop-in helper that (for either jQuery or Prototype.js) stubs at the XHR layer so that requests never go out. You can then expect all you want about the request.
Then it lets you provide fixture responses for all your cases and then write tests for each response that you want: success, failure, unauthorized, etc.
It takes Ajax calls out of the realm of asynchronous tests and provides you a lot of flexibility for testing how your actual response handlers should work.
here is a simple example test suite
for an app js like this
var app = {
fire: function(url, sfn, efn) {
$.ajax({
url:url,
success:sfn,
error:efn
});
}
};
a sample test suite, which will call callback based on url regexp
describe("ajax calls returns", function() {
var successFn, errorFn;
beforeEach(function () {
successFn = jasmine.createSpy("successFn");
errorFn = jasmine.createSpy("errorFn");
jQuery.ajax = spyOn(jQuery, "ajax").andCallFake(
function (options) {
if(/.*success.*/.test(options.url)) {
options.success();
} else {
options.error();
}
}
);
});
it("success", function () {
app.fire("success/url", successFn, errorFn);
expect(successFn).toHaveBeenCalled();
});
it("error response", function () {
app.fire("error/url", successFn, errorFn);
expect(errorFn).toHaveBeenCalled();
});
});
When I specify ajax code with Jasmine, I solve the problem by spying on whatever depended-on function initiates the remote call (like, say, $.get or $ajax). Then I retrieve the callbacks set on it and test them discretely.
Here's an example I gisted recently:
https://gist.github.com/946704
Try jqueryspy.com
It provides an elegant jquery like syntax to describe your tests and allows callbacks to test after the ajax has complete. Its great for integration testing and you can configure maximum ajax wait times in seconds or milleseconds.
I feel like I need to provide a more up-to-date answer since Jasmine is now at version 2.4 and a few functions have changed from the version 2.0.
So, to verify that a callback function has been called within your AJAX request, you need to create a spy, add a callFake function to it then use the spy as your callback function. Here's how it goes:
describe("when you make a jQuery AJAX request", function()
{
it("should get the content of an XML file", function(done)
{
var success = jasmine.createSpy('success');
var error = jasmine.createSpy('error');
success.and.callFake(function(xml_content)
{
expect(success).toHaveBeenCalled();
// you can even do more tests with xml_content which is
// the data returned by the success function of your AJAX call
done(); // we're done, Jasmine can run the specs now
});
error.and.callFake(function()
{
// this will fail since success has not been called
expect(success).toHaveBeenCalled();
// If you are happy about the fact that error has been called,
// don't make it fail by using expect(error).toHaveBeenCalled();
done(); // we're done
});
jQuery.ajax({
type : "GET",
url : "addressbook_files/addressbookxml.xml",
dataType : "xml",
success : success,
error : error
});
});
});
I've done the trick for the success function as well as the error function to make sure that Jasmine will run the specs as soon as possible even if your AJAX returns an error.
If you don't specify an error function and your AJAX returns an error, you will have to wait 5 seconds (default timeout interval) until Jasmine throws an error Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.. You can also specify your own timeout like this:
it("should get the content of an XML file", function(done)
{
// your code
},
10000); // 10 seconds

Categories

Resources