How to extend jQuery's ajax - javascript

This is rather a syntax question I am going to explain it jQuery's ajax functionality.
Let's say I want to control dataType of all ajax request according to url. For example url's with parameter &parseJSON=true should have a dataType of 'JSON' automatically.
For example:
$.myajax({url:'http://example.com&parseJSON=true'})
should be equivalent to
$.ajax({url:'http://example.com&parseJSON=true', dataType: 'JSON'})
Basically, I need to check for URL and add dataType parameter if needed.
Thanks

I think you can do this with a prefilter:
$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
// Modify options
if ( !options.dataType && /parseJSON=true/.test(options.url) ) {
return "json";
}
});
I don't have an environment to test this at the moment.
Edit: Just to clarify, you would use ajax requests just like you do now, with $.get, $.post, and $.ajax, you just don't have to supply a dataType anymore.

Related

Synchronous jQuery calls, without putting everything in the callback

Is it possible to get a JSON in jQuery synchronously without using the async: false option (which apparently has been deprecated)? I also would prefer not to put everything into the success function.
No, there is no other option than async: false. I wouldn't recommend it if there were.
For the success function, you can simply pass another function that will be executed.
For example:
$.ajax( {
url: myUrl,
type: 'POST',
success: myFunc
} );
function myFunc( datas ) {
// do what you should do in a success function
}
Since ajax methods on jQuery return a Deferred Object (jQuery 1.5+) you could also write
$.ajax({
url: myUrl,
type: 'POST'
}).done(function() {
// do what you should do in a success function
});
Not reasonably. Trying to force the request to be Synchronous without using asyc:false is possible, but a waste of effort in my opinion. In pretty much every scenario you want to use async:true, you will be able to accomplish all of the same things with async:true as you can with async:false. It's just a matter of how you structure your code.
If you look at the current version of the source file that executes the AJAX request:
https://github.com/jquery/jquery/blob/master/src/ajax/xhr.js
You will see it still uses the async field on the settings object, this field is passed directly into the Open method of the XMLHttpRequest object. So using the default implementation all you can do, is set "async: false".
if ( s.username ) {
xhr.open( s.type, s.url, s.async, s.username, s.password );
} else {
xhr.open( s.type, s.url, s.async );
}
Now assuming you are really stubborn and want to do this without setting "async:false", you could get really bold and write a custom ajaxTransport and register it with a custom data type.
Here is an example I wrote that creates a custom transport object with a send and abort method, and registers it with the dataType 'mine'. So when you specify dataType 'mine' in your ajaxSettings object it will use this custom transport instead of the one built into jQuery. http://jsfiddle.net/xrzc7/ Notice there are two ajax requests one with the 'mine' dataType that show the alert, and one without the data type that does not show the alert. My ajaxTransport in this example isn't fully functional, its just to illustrate that you can swap in your own send function.
I wouldn't advise writing your own ajaxTransport for jQuery because it really isn't neccessary in my opinion, but to answer your question I'm suggesting it as an option.
You should pay close attention to how the default ajaxTransport in jquery is written, and how it interacts with the settings object and callback methods when writing your custom ajaxTransport. Your send function would obviously force a "false" value as the async parameter of the XMLHttpRequest.open method.
https://github.com/jquery/jquery/blob/master/src/ajax/xhr.js - this is the current source code for the default ajaxTransport mechanism.
Hope this helps, or perhaps persuades you to always use async:true. :-D

jQuery: getJSON + SunlightLabs API help requested

I'm having trouble pulling a specific element from an API call using jQuery's getJSON function. I'm trying to use SunlightLab's congress API to pull specific info about legislators. In the example below I'm trying to pull a legislator's website:
$.getJSON("http://services.sunlightlabs.com/api/legislators.get.json?apikey=[api key]&lastname=Weiner&jsonp=?" , function(data) {
alert("hello from sunlight");
alert(data.response.legislator.website);
});
Using the above code, the first alert shows up but the second alert does not even occur. I understand that getJSON should be using JSONP in this instance, and I think I have that set up correctly, ending my URL with '&jsonp=?'.
Putting the URL in my getJSON function into a web browser gives me this:
?({"response": {"legislator":
{"website":
"http://weiner.house.gov/", "fax":
"202-226-7253", ... etc.
I'm a little thrown by the '?' showing up at the beginning of this, but if the first alert is showing up then the request must be succeeding...
The URL you're using is setting the JSONP callback to be equal to ?, which means its injecting a JavaScript function called ? with an argument of a JavaScript object. This is invalid. So, the request is succeeding, but the wrapper function you've defined isn't being called (and isn't valid).
You could change the URL so that its jsonp=callback (or some other handler function name), and then define a function called callback that handles an argument that expects the object.
One way to (automatically) trigger JSONP support in jQuery is to switch the key to be called 'callback' so that it signals to jQuery that you're doing a JSONP call. ie, callback=callback.
EDIT: As Drackir points out, jQuery provides a setting in $.ajax for letting it define it's own callback function name, but you need to signal to it that its a JSONP call by setting dataType: 'jsonp' in the $.ajax call.
The question mark is there because you specified the JSONP callback function to be ? in your query string (ie. &jsonp=?). Due to security concerns (specifically the same-origin policy) you cannot do an AJAX request to a site outside the same domain as the page you're on. To get around this, JSONP works by creating a script tag, with the SRC set to the URL of the script on the other site. This will load the external JavaScript file and run whatever code is there. Now, in order to link that external code with your JavaScript, the external API takes the name of a function to call (&jsonp=functionnametocall). The returned JavaScript calls that function and passes in the data it's trying to return as a JSON object as the first argument.
So, the reason you see the question mark when you go there is because you're passing a question mark to the jsonp query string parameter. jQuery will automatically convert the question mark in a url such as http://www.test.com/api/apikey=292929&callback=? to a uniquely named function. This is handled in the background by jQuery so you don't have to think about it.
Now, that said, I don't know if jQuery detects if the name of the callback parameter as being something other than callback=?. $.getJSON() however is a short form for the longer:
$.ajax({
url: url,
dataType: 'json',
data: data,
success: callback
});
I suggest you try using $.ajax() directly and set the jsonp setting equal to "jsonp". This tells the $.ajax() method that the query string parameter is called jsonp and not callback. So like this essentially:
$.ajax({
url: url,
dataType: 'json',
data: data,
success: callback,
jsonp:"jsonp"
});
More information: $.getJSON | $.ajax()
OK, OK, so it was a rather simple fix, adding a line to the the example given by #Drackir. The missing piece was 'cache: true' within the ajax settings. The final working code looked like this:
$.ajax({
url: 'http://services.sunlightlabs.com/api/legislators.get.json?apikey=[api key]7&lastname=Weiner',
dataType: 'jsonp',
cache: true,
jsonp: 'jsonp',
success: function(data) {
alert("hello from ajax") ;
alert(data.response.legislator.website);
}
});
I'm not sure why 'cache: true' is needed in this case. Thanks for the help.

When to use jQuery.ajax and when to use jQuery.post?

It seems, at the first glass, that we can use either of those. I'm wondering, however, when should we use one or the other, assuming a scenario where we can do the same thing with any of those two.
Thanks in advance,
MEM
jQuery.post is a shorthand method which calls jQuery.ajax.
If you don't need any functionality not supported by the shorthand, you might as well use it.
It's defined like this:
post: function( url, data, callback, type ) {
// shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) {
type = type || callback;
callback = data;
data = {};
}
return jQuery.ajax({
type: "POST",
url: url,
data: data,
success: callback,
dataType: type
});
},
The $.post is actually derived from $.ajax. You can use $.post when you want want to set the POST method in your request. $.ajax allows you to set both GET and POST request methods.
Using $.ajax allows you to set callbacks for failure, and completion, while $.post has callback only for success. Also, $.ajax allows to set a callback to be invoked before the sending of the request and set other useful parameters as timeout time , username or password if the target script needs authentication.
In short, $.post is a useful shortcut to use in the simpler situation, while $.ajax offers full control on the request.

How does this cross-domain request work?

$.ajax(
{
url : "http://search.twitter.com/search.json?q=google&lang=en&rpp=10&since_id=&callback=?",
dataType : 'json',
success : function(data)
{
alert(data.results.length);
}
});
How exactly is this working ? I mean the cross-domain request.
jQuery detects the callback=? part of your URL and automatically switches the dataType from 'json' to 'jsonp'.
JSONP is a JSON query that is not made using XMLHttpRequest but by adding a script tag to your page. Calling back into your script is handled by the caller giving the name of a JavaScript function to execute when the script loads. This is why cross-domain is working.
jQuery will handle JSONP transparently for you in a $.ajax request. The manual (and to me cleaner) way to do this is to define a 'jsonp' dataType and use the placeholder ? for the callback name in the URL. jQuery will automatically replace the ? with an appropriate value to trigger your success callback.
$.ajax(
{
url : "http://api.twitter.com/1/users/show/google.json&jsoncallback=?",
dataType : 'jsonp',
success : function(data)
{
alert(data.results.length);
}
});
jQuery defines your callback function in the global scope, then substitutes callback=? in the URL with callback=nameItGaveTheFunction.
It then functions as a normal JSONP request; using script tags, and wrapping the response in the callback function.
I believe that jQuery realises it's cross domain and so adds a script tag to the page header with the appropriate src attribute (rather than firing of an ajax request). This loads the JSON and then fires the callback.

jQuery $.post - how to call a callback function if $.post fails and or if the response is not the type you expect

Here's the thing, I have a jquery click event handler, that calls a post on click.
The type that it expects (4th parameter of $.post()) is "json". However, on the
server side; there are two responses to the post: it's either json or html response. The problem is, if it returns html, the callback function isn't called (because the $.post expects a json?).
How can I react to this? I want something that if the server side script returns a json, execute callback, otherwise do another. Is that possible? Can I check the response type with $.post?
You'll most likely want to use the generic jquery.ajax function. In particular the dataType: 'text' property should allow you to parse your return value in whatever method works for you. You can also use the parseJSON function
$.ajax({
url: 'url',
type: 'post'
dataType: 'text',
success: function(text) {
if (json) {
var obj = $.parseJSON(text);
} else {
var html = $(text);
}
}
});

Categories

Resources