$.ajax call with async:false and timeout expected - javascript

I've a web application which calls a webservice with ajax. This webservices returns me the configuraiton for my app, so the ajax call needs to be set at {async:false}.
Everything works fine when my server is up, but in the case it's not, my browser just freezes. Even if I set a timeout in my ajax call setup.
I've a error handler function which is never called even if the timeout is passed.
Someone has ever been confronted to that situation ?
#Edit : My problem can be solved by doing asynchronous call

As the browser is single threaded it would be better to process the config
returned in the callback success, and handle any errors in the error callback.
$.ajax({
url: "mydomain.com/url",
type: "GET",
dataType: "json",
data: $.param( $("Element or Expression") ),
complete: function() {
//called when complete
},
success: function() {
//called when successful
},
error: function() {
//called when there is an error
},
});

Related

Ajax Request sometimes causes `XHR failed loading: POST` error

I am trying to run a simple Ajax Request to pass a JSON object from my Javascript file to my Python file in Django. However half the time, I get the error XHR failed loading: POST when I run it as follows:
var csrf = $("[name=csrfmiddlewaretoken]").val()
$.ajax({
type: "POST",
url: "/fridge",
data: {
"fridgeitems": JSON.stringify(fridge),
"csrfmiddlewaretoken": csrf
},
dataType: "json",
timeout: 5000,
}).done(function(data) {
console.log(data.fridge);
}).fail(function(jqXHR, status) {
alert('Request could not complete' + status);
});
})
// rest of code
In my python file:
fridgeitems = request.POST['fridgeitems']
# do something with the data
response_data = json.dumps(fridgeitems)
return JsonResponse({"fridge": fridgeitems}})
I think what is happening is that when the Ajax request is placed the rest of the code runs, finishes and quits the function before ajax call has time to load. I have tried including timeout in my Ajax call however this appears to do nothing. How can I make the function wait for the Ajax call to finish?
Your problem is most likely that your request is timing out after a while of not getting response from the server. One likely cause is due to a slow network.
To handle this, do either or both of two things:
1. Handle the case where an request doesn't complete with the fail() method of the jqXHR object.
2. Include a timeout in the ajax request settings.
I illustrate using the combined strategy below:
var csrf = $("[name=csrfmiddlewaretoken]").val();
$.ajax({
method: "POST",
url: "/fridge",
data: {
"fridgeitems": JSON.stringify(fridge),
"csrfmiddlewaretoken": csrf,
},
dataType: "json",
timeout: 5000 // 5000ms
}).done(function(data) {
// is called if request is successful
console.log(data.fridge);
}).fail(function(jqXHR, status) {
// is called if request fails or timeout is reached
alert('Request could not complete: ' + status);
});
Notice, the use of the jQuery deferred objects methods: done() and fail() instead of sucess() and error(). The later is deprecated.

Jquery ajax response not calling Success method

I am pretty much new to ajax and working on jquery ajax request. Ajax callback is not calling success method. Interaction is between cross-site domains.
My AJAX request looks like
$.ajax({
timeout: 20000,
url: 'test.com',
crossDomain: true,
dataType: 'jsonp',
success: function (data) {
console.log('callback success');
this._cache = data;
localStorage.token = data.access_token;
} });
There are no errors in this call.
This ajax request is not calling success function.Request is returning json data. it's just success method is not getting called.
This ajax request is not calling success function.
Get request is getting fired successfully. I can even trace the response in fiddler with 200 http response.For some reason success method is not getting called.
it's returning json object, which I've traced in fiddler
You're telling jQuery to expect a JSONP response, so it is trying to execute the JSON document as if it were a JavaScript script (because that is what JSONP is). This fails because it is not JSONP.
Either return JSONP instead of JSON or (assuming the server returns the correct Content-Type) remove dataType: 'jsonp',.
ok... I came here with the same problem... and when I read that specifying datatype:jsonp never calls success as a callback per #mondjunge from a comment above, it started me thinking about some behavior I saw earlier from my code and that maybe datatype:json might have the same behavior for what ever reason here too.
So after reading this page I took out my datatype declaration from my ajax request and my servlet returned the proper data payload, returned a 200, and jquery called the success function finally and modified my DOM.
All those steps happened except the last one until I removed my datatype from my ajax call. NOT what I was expecting!
Hopefully someone else can shed some light on why this happens... for now at least the few that don't lose their minds to this issue that find this post can do this in the mean time.
Check if your ajax is executed
Check it's status. If response code is != 200, than you should add error method also, for error handling.
Try this:
$.ajax({
timeout: 20000,
url: 'test.com',
method: 'GET',
crossDomain: true,
dataType: 'jsonp',
success: function (data) {
console.log('callback success');
this._cache = data;
localStorage.token = data.access_token;
},
error: function(xhr, error){
console.debug(xhr); console.debug(error);
},
});

Delay between repeated AJAX call to a web method

I have a ASP.Net web app with jquery implemented on the client side. within a while loop, the client side jquery script makes an asynchronous call to a web method in the server side code. The call returns the status of a long running server side task which jquery uses to update the user. The goal is to have jquery repeatedly call the server until the status is complete, once done it breaks out of the while loop and notifies the user thatthe task is complete.
My problem is that the below code runs in a while loop, but I want to make it delay or sleep between each call in order to prevent overwhelming the server with status requests. I tried calling setTimeout in the code below, but it only works with the initial ajax call, every subsequent call occurs back to back. Is there a way to efficiently delay each subsequent call to the server? Is this the most efficient way to achieve the kind of behavior I'm describing? Ideally I'd like a 2-5 second delay between each call.
I have the following code
Client Jquery:
var alertTimerId;
$('input[name=btnStatus]').click(function () {
var result = false;
//Loop while server reports task complete is true
while (!result) {
alertTimerId = setTimeout(function () {
$.ajax({
type: "POST",
url: "Default.aspx/GetStatus",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
success: function (msg) {
if(msg.d != false)
result = msg.d;
},
error: function (xhr, ajaxOptions, thrownError) {
alert('AJAX failure');
}
});
}, 2000);
if (count > 0) {
count--;
}
}
});
Server Side ASP
[System.Web.Services.WebMethod]
public static bool GetStatus()
{
return result;
}
How about something like the following? The idea is that the Ajax call is encapsulated in a function, doAjax(), and then from within the Ajax success handler if the result is false you use setTimeout() to queue up another call to doAjax, otherwise you take whatever action you want to take for a true result. (You could optionally call doAjax() from the Ajax error handler too.)
$('input[name=btnStatus]').click(function () {
function doAjax() {
$.ajax({
type: "POST",
url: "Default.aspx/GetStatus",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
success: function (msg) {
if (!msg.d)
setTimeout(doAjax, 2000);
else {
// Success! Notify user here
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert('AJAX failure');
}
});
}
doAjax();
});
(Note: I've removed the if statement with count, since it seemed to have no relevance to the question. If your real code uses it just update it within the Ajax success handler too.)
Underscore.Js has a .throttle() helper function:
throttle_.throttle(function, wait)
Creates and returns a new, throttled version of the passed function, that, when invoked
repeatedly, will only actually call the original function at most once
per every wait milliseconds. Useful for rate-limiting events that
occur faster than you can keep up with.
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);

ajax calls to controllers. How to indicate success, complete, and error

If I make an ajax call to a controller.... what needs to happen in the controller so that the ajax call then calls
1) complete:
2) success:
3) error:
4) any other callbacks that exist.
For ex. I have this ajax call.
$.ajax({
url: "/ContactPartial/ContactUs",
type: "POST",
data: JSON.stringify(data),
dataType: 'json',
contentType: "application/json; charset=utf-8",
complete: function () { },
success: function () { },
error: function () { }
});
In other words, what can I do inside /ContactPartial/ContactUs to control which of the 3 (complete,success,error) gets called after the controller code executes.
Also, how is this related to related to return Json(new {some: data});
These three callbacks are related to the status of the Ajax call. These are called depending on success of the call. For complete details refer to the documentation
So, if the server responds with a success (200), then both the Success and the Complete handlers would be called. In the complete handler, you might put some code to dismiss a modal window (regardless of success or error), and in the success function, you might put code to let the user know the call was successful, reload a grid view, etc. Also, keep in mind that the callback functions don't have to be anonymous functions, they can be defined functions that are shared among several Ajax calls.
EDIT:
If you are wanting to force the server to generate an error, take a look at:
The HttpResponse class, specifically the StatusCode property
This SO post explains more too (generating a 401 error)

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