Globally filter ajax success handlers

£可爱£侵袭症+ 提交于 2019-12-11 04:01:12

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!