More often than not when using 3rd party Javascript widgets/plugins/frameworks is that they don't behave in exactly the way that you want forcing you to change tactics, write some horribly messy boilerplate code, hack the original code or look for alternatives. The proxy pattern is a useful pattern that provides a sort of AOP-lite technique that can be used to transparently manage 3rd party code without having to make breaking changes or repeating horrible code from a single point in the code.
Functions are 1st class objects in JavaScript and this is the feature that powers this pattern. Imagine the setup below,
// AJAX Object
var XHR = {
get : function(url, callback){
// perform ajax call to url
// call the callbakc with the returned data
}
}
// specific internal ajax functions.
// These are 3rd party code that shouldn't be touched
function GetData(url, callback){
XHR.get(url, function(data){
var parsedData = parse(data);
callback(parsedData);
});
}
function GetData2(url, callback){ /* similar thing to GetData*/ }
...
function GetDataN(url, callback){ /* similar thing to GetData*/ }
Now imagine there are a set of URLs that require some sort of authentication token passed along with the request. How do we deal with that? Well some people would just hack the internal functions but that's a bad idea as it probably breaks other parts of the system. Another way to do it would be to write your own Ajax framework for the new calls you want to make but that's overkill. The proxy pattern can help here.
// THE PROXY BLOCK
(function(){
// create empty list of secured URLs
XHR.securedURLs = [];
// point to original function
var _get = XHR.get;
// create proxy function
XHR.get = function(url, callback){
// is url a secured url?
if(XHR.securedURLs.indexOf(url) > -1){
// append authentication token
url += "?authToken=" + XHR.token;
}
// call original get function with potentially updated url
_get(url, callback);
}
})();
XHR.token = "AUTH_TOKEN";
XHR.securedURLs.push("https://secured.kainos.com");
GetData("https://secured.kainos.com", function(d){ /* code */ } ); // via proxy
GetData("http://notsecured.kainos.com", function(d){ /* code */ } ); // via original
So basically if the URL is a secured URL (present in the XHR.securedURLs array) then there will be a bit of pre-processing done to the URL before the function is called. Otherwise the normal function is called. That is the primary aim of the proxy pattern - to enhance existing functionality - at the very least the proxied function should fall back to the original function otherwise other parts of the system could be come affected (unless you know what you are doing of course - cancelling illegal calls etc).