Extending jQuery ajax success globally - javascript

I'm trying to create a global handler that gets called before the ajax success callback. I do a lot of ajax calls with my app, and if it is an error I return a specific structure, so I need to something to run before success runs to check the response data to see if it contains an error code bit like 1/0
Sample response
{"code": "0", "message": "your code is broken"}
or
{"code": "1", "data": "return some data"}
I can't find a way to do this in jQuery out of the box, looked at prefilters, ajaxSetup and other available methods, but they don't quite pull it off, the bets I could come up with is hacking the ajax method itself a little bit:
var oFn = $.ajax;
$.ajax = function(options, a, b, c)
{
if(options.success)
{
var oFn2 = options.success;
options.success = function(response)
{
//check the response code and do some processing
ajaxPostProcess(response);
//if no error run the success function otherwise don't bother
if(response.code > 0) oFn2(response);
}
}
oFn(options, a, b, c);
};
I've been using this for a while and it works fine, but was wondering if there is a better way to do it, or something I missed in the jQuery docs.

You can build your own AJAX handler instead of using the default ajax:
var ns = {};
ns.ajax = function(options,callback){
var defaults = { //set the defaults
success: function(data){ //hijack the success handler
if(check(data)){ //checks
callback(data); //if pass, call the callback
}
}
};
$.extend(options,defaults); //merge passed options to defaults
return $.ajax(options); //send request
}
so your call, instead of $.ajax, you now use;
ns.ajax({options},function(data){
//do whatever you want with the success data
});

This solution transparently adds a custom success handler to every $.ajax() call using the duck punching technique
(function() {
var _oldAjax = $.ajax;
$.ajax = function(options) {
$.extend(options, {
success: function() {
// do your stuff
}
});
return _oldAjax(options);
};
})();

Here's a couple suggestions:
var MADE_UP_JSON_RESPONSE = {
code: 1,
message: 'my company still uses IE6'
};
function ajaxHandler(resp) {
if (resp.code == 0) ajaxSuccess(resp);
if (resp.code == 1) ajaxFail(resp);
}
function ajaxSuccess(data) {
console.log(data);
}
function ajaxFail(data) {
alert('fml...' + data.message);
}
$(function() {
//
// setup with ajaxSuccess() and call ajax as usual
//
$(document).ajaxSuccess(function() {
ajaxHandler(MADE_UP_JSON_RESPONSE);
});
$.post('/echo/json/');
// ----------------------------------------------------
// or
// ----------------------------------------------------
//
// declare the handler right in your ajax call
//
$.post('/echo/json/', function() {
ajaxHandler(MADE_UP_JSON_RESPONSE);
});
});​
Working: http://jsfiddle.net/pF5cb/3/

Here is the most basic example:
$.ajaxSetup({
success: function(data){
//default code here
}
});
Feel free to look up the documentation on $.ajaxSetup()

this is your call to ajax method
function getData(newUrl, newData, callBack) {
$.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
url: newUrl,
data: newData,
dataType: "json",
ajaxSuccess: function () { alert('ajaxSuccess'); },
success: function (response) {
callBack(true, response);
if (callBack == null || callBack == undefined) {
callBack(false, null);
}
},
error: function () {
callBack(false, null);
}
});
}
and after that callback success or method success
$(document).ajaxStart(function () {
alert('ajax ajaxStart called');
});
$(document).ajaxSuccess(function () {
alert('ajax gvPerson ajaxSuccess called');
});

Related

Using custom function as parameter for another

I'm currently dealing with refactoring my code, and trying to automate AJAX requests as follows:
The goal is to have a context-independent function to launch AJAX requests. The data gathered is handled differently based on the context.
This is my function:
function ajaxParameter(routeName, method, array, callback){
//Ajax request on silex route
var URL = routeName;
$.ajax({
type: method,
url: URL,
beforeSend: function(){
DOM.spinner.fadeIn('fast');
},
})
.done(function(response) {
DOM.spinner.fadeOut('fast');
callback(response);
})
.fail(function(error){
var response = [];
response.status = 0;
response.message = "Request failed, error : "+error;
callback(response);
})
}
My problem essentially comes from the fact that my callback function is not defined.
I would like to call the function as such (example)
ajaxParameter(URL_base, 'POST', dataBase, function(response){
if(response.status == 1 ){
console.log('Request succeeded');
}
showMessage(response);
});
I thought of returning response to a variable and deal with it later, but if the request fails or is slow, this won't work (because response will not have been set).
That version would allow me to benefit the .done() and .fail().
EDIT : So there is no mistake, I changed my code a bit. The goal is to be able to deal with a callback function used in both .done() and .fail() context (two separate functions would also work in my case though).
As far as I can see there really is nothing wrong with your script. I've neatened it up a bit here, but it's essentially what you had before:
function ajaxParameter (url, method, data, callback) {
$.ajax({
type: method,
url: url,
data: data,
beforeSend: function(){
DOM.spinner.fadeIn('fast');
}
})
.done( function (response) {
DOM.spinner.fadeOut('fast');
if (callback)
callback(response);
})
.fail( function (error){
var response = [];
response.status = 0;
response.message = "Request failed, error : " + error;
if (callback)
callback(response);
});
}
And now let's go and test it here on JSFiddle.
As you can see (using the JSFiddle AJAX API), it works. So the issue is probably with something else in your script. Are you sure the script you've posted here is the same one you are using in your development environment?
In regards to your error; be absolutely sure that you are passing in the right arguments in the right order to your ajaxParameter function. Here's what I am passing in the fiddle:
the url endpoint (e.g http://example.com/)
the method (e.g 'post')
some data (e.g {foo:'bar'})
the callback (e.g function(response){ };)
Do you mean something like this, passing the success and fail callbacks:
function ajaxParameter(routeName, method, array, success, failure) {
//Ajax request on silex route
var URL = routeName;
$.ajax({
type: method,
url: URL,
beforeSend: function () {
DOM.spinner.fadeIn('fast');
}
}).done(function (response) {
DOM.spinner.fadeOut('fast');
success(response);
}).fail(function (error) {
var response = [];
response.status = 0;
response.message = "Request failed, error : " + error;
failure(response);
})
}
Called like:
ajaxParameter(
URL_base,
'POST',
dataBase,
function(response){
//success function
},
function(response){
// fail function
}
);

How to optimize (minimize) jQuery AJAX calls

I have over 50 AJAX calls from different functions of my code. All these calls have a similar structure with different data/url/callback params:
var jqXHR = $.post('/dba/port.php', {
mode: "del_wallfunds",
pdata: cdata,
wname: wName
},
function (data) {}, "json")
.done(function (data) {
var msg = data.msg;
if (msg.indexOf("Error") == -1) {
alertify.success(msg);
delSelected(selGroup);
} else {
alertify.error(msg);
}
})
.fail(function () {
alertify.error("Error .....");
});
I am thinking how to write a function that would return that var jqXHR to minimize the total size of the code. It is not a problem to pass all static variables like URL, error strings etc. But the problem is that all callback functions on ".done" are different and I don't know how to pass these callback functions as variables.
One way would be to call a single "universal" function on .done and pass a "switch" variable to that function, but it doesn't seem to be an elegant solution.
Any suggestions how to it in some elegant way?
Thanks
Either pass the done callback function as an argument when calling your function:
function ajaxCall(url, data, doneCallback) {
return $.post(url, data, doneCallback, "json").fail(...);
// or
return $.post(url, data, function() {}, "json").done(doneCallback).fail(...);
}
var jqXhr = ajaxCall('yoururl.php', {key: 'value'}, function(data) {
// do something
});
Or return the jqXhr object from the function, and assign the done callback then:
function ajaxCall(url, data) {
return $.post(url, data, function() {}, "json").fail(...);
}
var jqXhr = ajaxCall('yoururl.php', {key: 'value'});
jqXhr.done(function(data) {
// do something
});
Alternatively switch to using jQuery.ajax() instead, and pass the entire options object in:
function ajaxCall(options) {
return $.ajax(options).fail(...);
}
var jqXhr = ajaxCall({
url: 'yoururl.php',
data: {key: 'value'},
dataType: 'json'
});
jqXhr.done(function(data) {
// do something
});
You can try to :
turn "request successfully returned a treatment error" into a "rejected request",
put the "alertify" processing in a common callback
Here is a sketch of what this could give :
function myAjaxApi(url, data){
var myAjaxCall = $.post(url, data, function (data) {}, "json")
.then(function (data) {
// using .then : change "request succesful with error state"
// to "rejected state"
var msg = data.msg;
if (msg !== undefined && msg.indexOf("Error") >= 0) {
var dfd = $.Deferred();
// try to match the same signature as the "error" option
dfd.reject(this, msg);
return dfd;
} else {
return data
}
});
myAjaxCall.done(function(data){
if (data.msg) {
alertify.success(data.msg);
}
}).fail(function (jqxhr, msg) {
if (!msg) { msg = "Error ....."; }
alertify.error(msg);
});
return myAjaxCall;
}
//usage
myAjaxApi('/dba/port.php', {mode: "del_wallfunds", pdata: cdata, wname: wName})
.done(function (data) {
// the ".done()" queue will not be executed if msg contains "Error" ...
delSelected(selGroup);
});
Some parts should be written with more care ; the above example is meant to illustrate how you can wrap your repeated ajax calls inside a common api.

Dojo Get data from server and store in a variable using xhrGet

I have the following function:
loadMsgBody: function (id) {
return dojo.xhrGet({
url: "myurl",
handleAs: "text",
content: {
id: id
},
load: function (response) {
return response;
},
error: function (response) {
alert(response);
}
});
}
And calling it:
var text = "";
this.loadMsgBody(this.msgId).then(function (response) {
text = response;
});
Now I expect to get the return value of the function but instead I am getting an empty value for text. However, in Firebug I do see the response from the server with the correct value. I've searched and found these links : DOJO xhrGet how to use returned json object?
and:
Using hitch / deferred with an xhrGet request
But I still can't get and store the data with the above code. I don't want to do the manipulation inside the xhrGet call, I want to retrieve the data and use as it will be used multiple times.
Is there anything I am missing?
Dojo's XHR methods return instances of the class dojo/Deferred, because they are asynchronous. What this means is that the functions returns before the value of the response is available. In order to work with the results of the asynchronous response you need to wait for it to return. Dojo exposes this using a uniform API, Deferreds. Instances of the dojo/Deferred class have a method then. The then method takes a function as a parameter. That function will execute once the Deferred have been resolved (in this case, when the request has completed).
var deferred = loadMsgBody();
deferred.then(function(response){
//work with response
});
I would try changing your load function to evoke your callback function:
loadMsgBody: function (id, callback) {
return dojo.xhrGet({
url: "myurl",
handleAs: "text",
content: {
id: id
},
load: function (response) {
if(callback) {
callback(response);
}
},
error: function (response) {
alert(response);
}
});
}
Try this:
loadMsgBody: function (id, callback) {
return dojo.xhrGet({
url: "myurl",
handleAs: "text",
content: {
id: id
},
load: function (response) {
callback.apply(null,[response]);
},
error: function (response) {
alert(response);
}
});
}
Then:
var text = "";
this.loadMsgBody(this.msgId, function (response) {
text = response;
console.log("text:",text); // this will show your return data
});
console.log("text:",text); // this will show empty data because ajax call is asynchrize, at this time , data not return yet.
setTimeout(function(){
console.log("text:",text); // this will show your return data again because ajax call should have finished after 30000 ms
},30000)

How to return a value inside AJAX function to parent in javascript?

I'm trying to return true or false to a function depending on the response of an AJAX function inside of it but I'm not sure how should I do it.
(function($) {
$('#example').ajaxForm({
beforeSubmit : function(arr, $form, options) {
var jsonStuff = JSON.stringify({ stuff: 'test' });
$.post('/echo/json/', { json: jsonStuff }, function(resp) {
if (resp.stuff !== $('#test').val()) {
// Cancel form submittion
alert('Need to type "test"');
return false; // This doesn't work
}
}, 'json');
},
success : function() {
alert('Form sent!');
}
});
})(jQuery);​
I made a fiddle to illustrate this better:
http://jsfiddle.net/vengiss/3W5qe/
I'm using jQuery and the Malsup's Ajax Form plugin but I believe this behavior is independent of the plugin, I just need to return false to the beforeSubmit function depending on the POST request so the form doesn't get submitted every time. Could anyone point me in the right direction?
Thanks in advance!
This is not possible to do when dealing with async functions. The function which calls post will return immediately while the ajax call back will return at some point in the future. It's not possible to return a future result from the present.
Instead what you need to do is pass a callback to the original function. This function will eventually be called with the result of the ajax call
var makePostCall = function(callback) {
$.post('/echo/json/', { json: jsonStuff }, function(resp) {
if (resp.stuff !== $('#test').val()) {
// Cancel form submittion
alert('Need to type "test"');
callback(false);
} else {
callback(true);
}}, 'json');
};
Then switch the code which expected a prompt response from makePostCall to using a callback instead.
// Synchronous version
if (makePostCall()) {
// True code
} else {
// false code
}
// Async version
makePostCall(function (result) {
if (result) {
// True code
} else {
// False code
}
});
you can put async:false parameter to ajax request then you can control future responce and send back the result to parent. see following main lines enclosed within ***
add: function (e, data) {
//before upload file check server has that file already uploaded
***var flag=false;***
$.ajax(
{
type: "POST",
dataType:'json',
url:"xyz.jsp",
***async:false,***
data:{
filename : upload_filename,
docname : upload_docname,
userid : upload_userid,
},
success:function(data)
{
***flag=true;***
},
error:function(request,errorType,errorMessage)
{
alert ('error - '+errorType+'with message - '+errorMessage);
}
});
***return flag;***
}

Function to retrieve value from AJAX request

How do you write a function that returns a value fetched from server via $.get?
This is what I have tried, which does not work:
function getMessage(key) {
$.get("/messages.json", function(data) {
return data.messages[key];
}, "json");
}
Any ideas?
Because Ajax requests are asynchronous. That is why you have to pass a callback to $.get, to handle the data once it is available. But the getMessage function returns before the $.get callback is executed.
You have to pass a callback that is doing something with the return value. E.g.:
function getMessage(key, cb) {
$.get("/messages.json", function(data) {
cb(data.messages[key]);
}, "json");
}
getMessage('foo', function(data) {
alert(data);
});
Of course you can also pass the callack directly to $.get and handle the data extraction there:
function getMessage(cb) {
$.get("/messages.json", cb);
}
There are two ways to handle this: use a synchronmous call via $.ajax or pass in a callback to your function instead of having it return a value. The latter is the canonical way to deal with AJAX since it retains the asynchronous nature of the call.
Asynchronous
function processMessage(key,elem,cb) {
$.get('/messages.json', function(data) {
if (cb && typeof(cb) === 'function') {
cb.apply(elem,data.messages[key]);
}
}
}
$('.something').each( function() {
processMessage('somekey', this, function(msg) {
$(this).append(msg);
});
});
Synchronous - try not to do it this way, since you'll lock your browser until it's done.
function getMessage(key)
{
var result = '';
$.ajax({
url: '/messages.json',
aSync: false,
type: 'get',
dataType: 'json',
success: function(data) {
result = data.messages[key];
}
});
return result;
}
$('.something').each( function() {
var msg = getMessage('somekey');
$(this).append(msg);
});
Note: these are untested.

Categories

Resources