Centralize capturing of errors in JQuery - javascript

I have 15 $.ajax calls that are JSONP. I'm using this workaround to prevent javascript exceptions like:
Uncaught TypeError: jQuery878937344363463463_8761219911121421 is not a function
I'm using this code in error callback to prevent it from showing up in console.
window[callbackname] = function() {
window[callbackname] = null;
};
However, I think it's bad if I put that code in all my 15 AJAX calls. In AngularJS, we can intercept errors using $httpProvider.interceptors. This allows us to centralize logging rather than individually.
Does jQuery have a similar feature?

In jQuery, you can use $.ajaxSetup() to set shared options that all of your $.ajax calls will use.
See https://api.jquery.com/jquery.ajaxsetup/

Related

How can I monitor Backbone ajax requests?

I thought this would be easy b.c. Backbone uses jQuery and has a single access point I thought I could just do this:
Backbone.ajax = function() {
var xhr = Backbone.$.ajax.apply(Backbone.$, arguments);
// xhr.addEventListener("loadend", loadEnd);
return xhr;
};
but for some reason I can not load an event listener to the xhr object as I normally do.
I get an error stating that addEventListener is not a function.
See jqXHR:
The jQuery XMLHttpRequest (jqXHR) object returned by $.ajax() as of jQuery 1.5 is a superset of the browser's native XMLHttpRequest object.
It is not exactly the native XMLHttpRequest, so it might not behave exactly like the native one. There is no guarantee that it exposes methods like addEventListener unless it's documented. If you want to set something globally it's safer to use jquery.ajaxsetup

Is it a good idea to override jQuery's $.ajax with a thin Cache layer?

Will it be a good or a bad practice to override all ajax call in my Web App's JavaScript code with an "invisible" Cache layer?
It'd be something like (pseudo-code):
$.prototype.ajax = function(...) {
if( requested URL can be found in localStorage )
return dataFromLocalStorage; // as Deferred
data = invoke original $.ajax;
localStorage.setItem(key, data);
return data; // as Deferred
}
I can think of one pro: no refactoring is needed for existing ajax calls, and one con: future developers will be unaware of this functionality, as it disguises itself as a regular ajax call.
What do you think? Will it be a good practice or should I avoid it?
No, it is not a good idea to override the default behavior of $.ajax like this. Other code on your page including jQuery plugins might depend on the default behavior.
It is likely at some point you might want to get the freshest version of some data, if $.ajax always caches to localStorage there will be no way to do that. This could also lead to future debugging headaches when someone working on the code (including you) can't figure out why their AJAX calls keep returning stale data.
It would be much better to just implement the caching in a separate function. That way when you see a call to something like ajaxWithCaching it will be obvious that something more that a plain AJAX call is going on.
I wouldn't be overriding the default behavior of anything! If you change the way $.ajax works, what will you do when you're using a lightbox plugin (or literally anything) which relies on the normal functionality of $.ajax?
It would backfire terribly upon you.
Instead, create your own function which performs the caching, and uses $.ajax normally.
var cache={}; // Your Cache
function getArticle(id,callback){ // Your caching ajax-wrapping function (requires a callback)
// Require the arguments
if (arguments.length<2) throw "getArticle requires id and callback arguments";
// If the article is cached, pass it to the callback and return
var cachedArticle = id in cache
? cache[id]
: null;
if (cachedArticle) return callback(cachedArticle,true); // cached=true
// If that article isn't in the cache, perform an ajax call to get it
$.ajax({
url: "article.php",
success: function(data,textStatus,jqXHR){
cache[id] = data; // Cache it!
callback(data,false); // Pass it to the callback // cached=false
}
});
return true; // reporting that we launched an ajax request
}
Then to use it, you've got a pretty robust little function.
var ajaxWasUsed = getArticle(8, function(articleData,wasCached){
console.log("Got Article #8 "+(wasCached?"(from cache)":"(fresh ajax)")+":",articleData);
});

Using jQuery's getJSON() method

So I was reading through the code on Malsup's twitter plugin and I noticed he'd written his own method to handle jsonp but with timeouts and errors. I can only assume the built in jQuery method 'getJSON' doesn't have this functionality even though it clearly works fine.
So, should I continue to use Malsups version in my projects where I'm making JSONP requests or just stick with jQuery's method. I have emailed Malsup and Paul Irish to ask about why it was necessary to write this but I didn't hear back. Can't blame 'em really:)
$.getJSONP = function(s){
s.dataType = 'jsonp';
$.ajax(s);
// figure out what the callback fn is
var $script = $(document.getElementsByTagName('head')[0].firstChild);
var url = $script.attr('src') || '';
var cb = (url.match(/callback=(\w+)/) || [])[1];
if (!cb)
return; // bail
var t = 0, cbFn = window[cb];
$script[0].onerror = function(e){
$script.remove();
handleError(s, {}, "error", e);
clearTimeout(t);
};
if (!s.timeout)
return;
window[cb] = function(json){
clearTimeout(t);
cbFn(json);
cbFn = null;
};
t = setTimeout(function(){
$script.remove();
handleError(s, {}, "timeout");
if (cbFn)
window[cb] = function(){
};
}, s.timeout);
function handleError(s, o, msg, e){
// support jquery versions before and after 1.4.3
($.ajax.handleError || $.handleError)(s, o, msg, e);
}
};
If it's JSONP, you can use
$.getJSON(url + "&callback=?", [args]);
to get JSONP and call a function when it loads. The &callback=? query lets jQuery generate a random callback function in the global scope to respond to the JSONP call.
From the jQuery docs for getJSON(...)
Important: As of jQuery 1.4, if the
JSON file contains a syntax error, the
request will usually fail silently.
Avoid frequent hand-editing of JSON
data for this reason. JSON is a
data-interchange format with syntax
rules that are stricter than those of
JavaScript's object literal notation.
For example, all strings represented
in JSON, whether they are properties
or values, must be enclosed in
double-quotes. For details on the JSON
format, see http://json.org/.
Presumably, silent failure was not something they liked, hence the plugin. In your case, if you're making JSONP requests and find yourself using the onError, or onTimeout methods, then keep the plugin. I've not had to use JSONP in any real capacity, but I would assume that error handling is always nice to have. In the link to the jQuery docs, there is good discussion on this towards the end of the comments
JQuery HowTo has a post specifically about using jQuery, JSONP, and Twitter.
Twitter JSON(P) API URL:
http://twitter.com/status/user_timeline/USERNAME.json?count=10&callback=JSONPcallbackFunction
Here is a code to use with jQuery’s
$.getJSON() function:
http://twitter.com/status/user_timeline/USERNAME.json?count=10&callback=?
We have put ? (question mark) for
callback function name so jQuery could
replace it with a dynamic one that it
has created.

How to deal with response data in ajaxComplete event

Say I have this code:
function onComplete(event, request, settings)
{
// How do I get the data? In the correct format?
}
$('body').ajaxComplete(onComplete);
In regular ajax success handlers, I can just access the data directly since it will be the first parameter to the handler. It will also be in the correct format (as long as the content-type was set right on the server).
How do I deal with the data on the ajaxComplete event?
You can use it like this, but it's not documented:
function onComplete(event, request, settings) {
var data = $.httpData(request, settings.dataType, settings);
}
The jQuery.httpData function is what's used internally to get data for the success handler, but you can use it directly. Please be aware that it is undocumented, and therefore subject to change without notice in new releases. For example in jQuery 1.4.3, it will be jQuery.ajax.httpData instead.
According to the the doc:
http://api.jquery.com/ajaxComplete/
I don't think you mean to fiddle with the data, because it doesn't pass any data to the handler. If you want data you better off using the set success property in regular Ajax.
This may not be the right handler to use if you want to get data as this is really intended more as a basic notification callback (for all hooked elements) when any AJAX calls completes.
To get to your data you should you might need to be more targeted in your approach and use the $.ajax() call or one of its variants like $.get() or $.getJSON(). See here

JQuery error property for error handler

I'm just playing around for the first time with jQuery's ajax functionality. I wanted to add a function that could handle any errors. So, in one of my client javascript blocks, I added the following line:
<script type="text/javascript">
....
$.ajax({ error: function () { alert('boo'); } })
....
</script>
I expected that this would bind the error handler, so that when an error occurs, it would fire the anonymous function included.
What happens instead though, is that it immediately fires the function on page load, as soon as it parses this line of code.
What am I doing wrong? What is the proper way to bind the ajax error handler?
I'm not sure if I understood your question correctly, let me know if I've misunderstood.
I assume that you are trying to create a generic ajax call error handler? If that's the case, you have got the wrong idea.
Are you are just trying to bind the event handler? In this case, you are executing it.
I would recommend you read and check out the examples on these jQuery API reference docs:
API/1.3/Events
Ajax/jQuery.ajax
Also check out the post link provided by F.Aquino and this SO post: JavaScript Exception Handling.
This is could be helpful too: Handling AJAX Errors With jQuery.
You want to change the global settings. Check jQuery documentation.
$.ajaxSetup({
error: function () { alert('boo'); }
});

Categories