问题
I am developing a single page ASP.NET MVC 3 application. All posts are done by ajax calls. The users can see almost everything on the page but some actions requires the user to login.
If an action requires login, i return a JSON
{unauthenticated: true}
if the user is not logged in. So i have several success handlers like:
success : function(response){
if(response.unauthenticated){
showLoginDialog();
} else {
doTheActualWork();
}
}
I want to do it in the global success handler. Like:
$(document).ajaxSuccess(function (event, XMLHttpRequest, ajaxOptions){
if(unauthenticated()){
preventTheLocalSuccess();
showLoginDialog();
}
});
And the local success handler will be:
success: function(response){
// No Checking
doTheActualWork();
}
Is there a way to do that?
回答1:
instead of returning JSON return the proper HTTP ERROR Code, which in this case would be a 401 Unauthorized
. Then you can use the ajaxError
method to handle it.
$(document).ajaxError(function (event, XMLHttpRequest, ajaxOptions){
switch (xhr.status) {
case 401: // Unauthorized
// Take action, referencing xhr.responseText as needed.
showLoginDialog();
return false;
break;
}
});
Furthermore you can extend your ajaxError conditions to handle other failed requests.
回答2:
You should take a look at the dataFilter property of $.ajax. This property accepts a function which executes just after you receive the request but before any handlers are executed. The main purpose of this is to preprocess data received before they are processed by jQuery itself. Therefore, you will receive the raw data. You can do intermediate processes there, like your login.
To patch this configuration to all ajax calls, we use $.ajaxSetup to predefine dataFilter
for all ajax requests. Therefore, each ajax request will have a dataFilter
handler execute before local handlers execute.
As for sample code, here's a demo, which pretty much works as expected:
function login() {
console.log('login initiated: you are not logged in');
}
$.ajaxSetup({
dataFilter: function (origdata, type) {
//the type is determined by the type you indicated in the ajax call
//if not json, we return the data unharmed
if (type !== 'json') return origdata;
//data filter receives the raw response. since we have determined it's json
//we parse it using jQuery's parseJSON to check the contents
var data = $.parseJSON(origdata);
if (data.auth) {
//if logged in, we just return the data
return origdata;
} else {
//otherwise, we execute the login
//since returning something is required, we return false so local handler
//data checks will fail against the false data
login();
return false;
}
}
});
//the url and data passed is for jsFiddle to work.
//logged in
$.post('/echo/json/', {
json: JSON.stringify({
auth: true
})
}, function (data) {
//in our handler, it's your normal "check data before use"
//if data is truthy, it skips this check and moves on
if(!data) return;
console.log('data retrieved successfully', data);
}, 'json');
//not logged in
$.post('/echo/json/', {
json: JSON.stringify({
auth: false
})
}, function (data) {
//since we returned false, the code stops at this check
if (!data) return;
console.log('you should not see this since data is false, per dataFilter return', data);
}, 'json');
来源:https://stackoverflow.com/questions/16259230/globally-filter-ajax-success-handlers