$.getJSON .always() method won't execute on HTTP error - javascript

I'm trying to retrieve some google calendar information using getJson. In some cases the calendars I'm trying to retrieve may or may not be available and I'll get either GET HTTP error 403 or 404, other times GET will be succesful. My problem is I need to execute some code even in the cases GET fails to receive the data. I thought that using the .always method would execute this code regardless but it turns out it won't execute when a 403 or 404 happens. I also tried specifically target this cases using .fail method with no success. Any idea?
Adding the code:
function AcquireGroupFeed(GroupDataBase) {
// For each group the calendar information is aquired and, if the events are
// relevant they are added to the feed.
// The group's calendar URL
var CalUrl = "http://www.google.com/calendar/feeds/" + GroupDataBase.calendarid +
"/public/full?alt=json-in-script&callback=?";
// Acquiring the data from Google.
$.getJSON(CalUrl, function(data) {PushToEventFeed(data, GroupDataBase);})
.always(function(){CheckAllGroupsAcquired();});
}

I recently learned that, by using the $.ajax call instead of .getJSON I can handle the error when I fail to retrieve the URL. The timeout setup should be defined for the error to be handled:
$.ajax({
url: URL,
dataType: 'json',
timeout: 3000,
success: function( data ) { successFunction();},
error: function( data ) { errorHandling(); }
});
With this, I was able to solve my problem.

You are in fact doing a JSONP request, since the domain where the page is hosted is different from the one in the AJAX request. JSONP does not function by using the normal XMLHTTPRequest interface (it uses script elements), and it does not support failure callbacks.
If you look under the error option for the $.ajax function, you will see this note:
This handler is not called for cross-domain script and cross-domain JSONP requests
The same applies to $.getJSON (since it is a wrapper for $.ajax).
If you need a failure callback, you will probably need to program it yourself, maybe based on a two-second timer, or something like that.

Related

"Security Err: Dom Exception" thrown when nesting ajax calls

Here's the issue. I'm extracting gmail contacts through an ajax call in javascript/jquery like this:
function getUserInfo() {
var xml_parse = "";
$.ajax({
url: SCOPE + '?max-results=9999&access_token=' + acToken
data: null,
success: function (resp) {
xml_parse = $.parseXML(resp);
callGmailHelperWebService(xml_parse);
},
dataType: "jsonp"
});
}
function callGmailHelperWebService(xml_parse) {
GmailHelperService.ConvertXMLToList(xml_parse, onSuccess, onFailed, null);
}
So, as you can see, if the initial ajax call is successful, i call a function which calls a web service that sits on the save server as my project (in fact, it's part of the project).
My web service (GmailHelperService) is wired up correctly, as I can definitely call it in other places (like right after this ajax call, for example). However, when I try to call it within the "success" portion of the ajax call, i get the following error:
Uncaught Error: SECURITY_ERR: DOM Exception 18
My theory is that this has something to do with cross-domain issues, but I can't understand why. And I certainly can't figure out how to fix this.
I'd appreciate any help.
JSONP is a data transfer method that involves sending your data in this format:
callback({"foo":"bar"});
As you can see, this is NOT xml. It is JSON wrapped in a callback method that will get executed when the request is done loading, thus allowing it to be cross-domain because it can be requested using a <script> tag.
You cannot simply change your dataType to JSONP and return xml, expecting it to work. XML != JSONP. You can however return XML in jsonp, for example, callback({"xml","... xml string here "}) but be mindful of quotes, all json keys and values must be wrapped in double quotes, inner-quotes need to be handled appropriately.
If your request is a same domain request (Same protocol, same subdomain, same domain, and same port,) then you can change your dataType to "XML" if you are returning XML. Otherwise, you need to either setup a proxy script to get the xml for you, or have your webservice return JSONP.
For example, the following urls are all considered cross-domain from each other.
http://example.com
http://www.example.com
https://example.com
https://www.example.com
http://example.com:8080
All of the above urls would be considered cross-domain, even if they are on the same server.

Call similar to $.get in $.ajax

I have the following code:
$.get(url, {}, checkResponse)
And the following function:
function checkResponse(content) {}
The parameter "content" here is the result of the "get". I wanted to implement $.ajax to able to wait for the process to complete before it jump to the next chunk of code. I tried the following code but it didn't work.
$.ajax({
async: false,
type: 'GET',
url: url,
success: function (data) {
alert(data.toString());
checkResponse(data);
},
error: function (data) {
alert("error");
}
});
Here's what happened, the alert for the data.toString() gives empty string value while it should give me the url page content, and after it hits the alert it jumps to the error section and displays the alert "error".
According to the discussion in the comments section you are trying to send cross domain AJAX calls to arbitrary urls on the internet. Due to the same origin policy restriction that's built into the browsers this is not possible.
Possible workarounds involve using JSONP or CORS but since you will be sending requests to arbitrary urls that you have no control over they might not be an option. The only viable solution in this case is for you to write a server side script that you will host on your domain acting as a bridge. This script will receive an url as parameter and send an HTTP request to this url in order to retrieve the result. Then it will simply return the result back to the response. Finally you will send an AJAX request to your own server side script.

Calling a web service in JQuery and assign returned Json to JS variable

This is my first time attempting working with JQuery, Json AND calling a web service.. So please bear with me here.
I need to call a webserivce using JQuery, that then returns a Json object that I then want to save to a javascript variable. I've attempted writing a little something. I just need someone to confirm that this is indeed how you do it. Before I instantiate it and potentially mess up something on my company's servers. Anyways, here it is:
var returnedJson = $.ajax({
type: 'Get',
url: 'http://172.16.2.45:8080/Auth/login?n=dean&p=hello'
});
So there it is, calling a webservice with JQuery and assigning the returned jsonObject to a javascript variable. Can anyone confirm this is correct?
Thanks in advance!
var returnedJson = $.ajax({
type: 'Get',
url: 'http://172.16.2.45:8080/Auth/login?n=dean&p=hello'
});
If you do it like this returnedJson would be an XHR object, and not the json that youre after. You want to handle it in the success callback. Something like this:
$.ajax({
// GET is the default type, no need to specify it
url: 'http://172.16.2.45:8080/Auth/login',
data: { n: 'dean', p: 'hello' },
success: function(data) {
//data is the object that youre after, handle it here
}
});
The jQuery ajax function does not return the data, it returns a jQuery jqHXR object.
You need to use the success callback to handle the data, and also deal with the same origin policy as Darin mentions.
Can anyone confirm this is correct?
It will depend on which domain you stored this script. Due to the same origin policy restriction that's built into browsers you cannot send cross domain AJAX requests. This means that if the page serving this script is not hosted on http://172.16.2.45:8080 this query won't work. The best way to ensure that you are not violating this policy is to use relative urls:
$.ajax({
type: 'Get',
url: '/Auth/login?n=dean&p=hello'
});
There are several workarounds to the same origin policy restriction but might require you modifying the service that you are trying to consume. Here's a nice guide which covers some of the possible workarounds if you need to perform cross domain AJAX calls.
Also there's another issue with your code. You have assigned the result of the $.ajax call to some returnedJson variable. But that's not how AJAX works. AJAX is asynchronous. This means that the $.ajax function will return immediately while the request continues to be executed in the background. Once the server has finished processing the request and returned a response the results will be available in the success callback that you need to subscribe to and which will be automatically invoked:
$.ajax({
type: 'Get',
url: '/Auth/login?n=dean&p=hello',
success: function(returnedJson) {
// use returnedJson here
}
});
And yet another remark about your code: it seems that you are calling a web service that performs authentication and sending a username and password. To avoid transmitting this information in clear text over the wire it is highly recommended to use SSL.

Problems reading json data with jquery.

I am having problems using jquery to grab json data from a web service that lies on a different subdomain from where my client side code is. When I access the exact same json data from a local text file, my code works fine.
The json data is coming from this address
var jsonFeed = https://crm.bmw.ca/webservices/RetailerLocator.ashx?language=en&callback=?
The MIME type of the data is text/html, however I have also tried application/json.
Here is one method of access
$.getJSON(jsonFeed, function (data) {
$.each(data, function (i, item) {
alert(item);
});
});
I've also tried this method, which came back with a parsererror. I've also tried this with a jsonp datatype
$.ajax(jsonFeed, {
crossDomain: true,
dataType: "json",
success: function (data, text) {
$.each(data, function (i, item) {
alert(item);
});
},
error: function (request, status, error) {
alert(status + ", " + error);
}
});
My code has to be entirely client side so a proxy isn't an option right now.
An example of someone with a very similar problem can be found here.
jQuery AJAX JSON dataType Conversion
You can only work within the confines of what is possible. Same-origin policy can't be subverted, although you can use things like cross-domain policy headers on each of your servers to essentially link them together. However, that's only supported in the newer crop of browsers, and you have to control all the servers in the network.
See: http://en.wikipedia.org/wiki/Same_origin_policy for more information on what you're up against.
While the returned JSON data should probably be of type text/json, the bigger problem is that the API call is not respecting your "callback" parameter. Since you're calling the API cross-domain you have to use JSONP which means your data should be returned inside of a function call. For example, if you navigate to https://crm.bmw.ca/webservices/RetailerLocator.ashx?language=en&callback=mycallback you should see something like this returned:
mycallback([{"RetailerID":1110,"Name":"BMW St. John's","Address":"120 Kenmount Road"...)
The fact that the callback function name specified in the "callback" argument isn't showing up as part of the returned data probably means that you're using an incorrect name for that parameter. Or, it could be that the system is not configured to allow cross-domain requests. You should contact the system admin and make sure the API allows cross-domain requests and also check the docs for that API and make sure you're using the correct callback parameter name.
So far as I can tell from playing with JSFiddle (http://jsfiddle.net/CEDB5/), the question/answer you mentioned is correct: unless crm.bmw.ca starts sending the correct MIME type you are stuck.

using a named function as the callback for $.getJSON in jQuery to satisfy Facebook request signing demands

I'm trying to access the Facebook API Admin.getMetrics method via jQuery. I'm correctly composing the request url on the server side (in order to keep my app secret secret). I'm then sending the url over to the browser to be request using jQuery.getJSON().
Facebook requires that I send a copy of all of my request params hashed with my application secret along with the request in order to verify my authenticity. The problem is that jQuery wants to generate the name of the callback function itself in order to match the name it gives to the anonymous function you pass in to be called when the data returns. Therefore, the name of the function is not available until jQuery.getJSON() executes and Facebook considers my request to be inauthentic due to a mismatched signature (the signature I send along does not include the correct callback param because that was not generated until jQuery.getJSON() ran).
The only way I can think of out of this problem is to somehow specify the name of my function to jQuery.getJSON() instead of allowing it to remain anonymous. But I cannot find any option for doing so in the jQuery AP.
The only thing that did the work for me were the following settings
jQuery.ajax({
url: fbookUrl,
dataType: "jsonp",
type: "GET",
cache: true,
jsonp: false,
jsonpCallback: "MyFunctionName" //insert here your function name
});
The use of jQuery.getScript turned out to be close to -- but not quite -- the answer. Using getScript eliminates jQuery's need to add the dynamically named anonymous function to the request params (though it will still do that if you go ahead and pass it an anonymous function as in the above code). However, the default in jQuery.getScript, as in all the other calls in jQuery's Ajax library, is to append a further additional argument _=12344567 (where 1234567 is really a time stamp). jQuery does this to prevent the browser from caching the response. However, this additional breaks my signing of the request just like the auto-named callback function.
With some help on #jquery, I learned that the only way to get jQuery not to mess at all with your params is to make the request using the base jQuery.Ajax method with the following arguments:
jQuery.ajax({
url: fbookUrl,
dataType: "script",
type: "GET",
cache: true,
callback: null,
data: null
});
(where fbookUrl is the Facebook API url I'm trying to request with its full params including the signature and the callback=myFunction). The dataType: "script" arg specifies that the resulting JSONP should be stuffed into a script tag on the page for execution, cache: true tells jQuery to allow the browser to cache the response, i.e. to skip the addition of the time stamp parameter.
You can pass the JSONP option to $.ajaxSetup that will allow you to fix the function name that gets called, the docs read as follows:
jsonp String
Override the callback function name in a jsonp request. This value will be used instead of 'callback' in the 'callback=?' part of the query string in the url for a GET or the data for a POST. So {jsonp:'onJsonPLoad'} would result in 'onJsonPLoad=?' passed to the server.
See here http://docs.jquery.com/Ajax/jQuery.ajax#options for more details
This is a better solution with a fixed callback:
window.fixed_callback = function(data){
alert(data.title);
};
$(function() {
$.getScript("http://api.flickr.com/services/feeds/photos_public.gne?tags=cats&tagmode=any&format=json&jsoncallback=fixed_callback", function(data) {
alert('done'); } );
});
The problem with this callback is you can only handle one kind of request at a time as the function is globally registered. The callback function would probably have to turn into a dispatcher for the different kinds of data that it could retrieve and call the appropriate function.

Categories

Resources