• ajax异步请求302分析


    1.前言

    遇到这样一种情况,打开网页两个窗口a,b(都是已经登录授权的),在a页面中退出登录,然后在b页面执行增删改查,这个时候因为授权原因,b页面后端的请求肯定出现异常(对这个异常的处理,进行内部跳转处理),b页面中的ajax请求的回调中就会出现问题,今天遇到了,有种恍然大悟的感觉,打开以前公司的网站发现全都没做任何处理......
    没遇到过错误,永远不知道错误会什么时候出现。

    2.问题:在ajax异步请求中,如果服务端出现内部跳转,如何在回调中处理

    我们先来看这样一个简单的ajax异步请求

    $.ajax({
        url: '/User/Add',
        type: 'post',
        data: data,
        success:function(data,status)
        {
    	    console.log('data:'+data);
       	    console.log('status:'+status);
        },
        complete: function(xhr){
            console.log(xhr.status);
        },
        error: function (xhr) {
       		debugger;
            console.log(xhr.status);
        }
    });    
    

    后端处理时,抛出异常,出现了内部重定向
    稍微简单解释一下,用的mvc,加了一个全局的异常,在Add方法中抛出异常,在OnException会进行捕获到这个异常,代码很简单也比较典型。

        public class GlobalHandlerErrorAttribute : HandleErrorAttribute
        {
            public override void OnException(ExceptionContext actionExecutedContext)
            {
                    actionExecutedContext.HttpContext.Response.Redirect("/User/Login");
            }
        }
    
            public ActionResult Add(UserModel model)
            {
                throw new HttpException("un authorize");
            }
    

    结果是什么?
    回调中会进入到success方法,输入data:是Login页面的整个内容,status:success ,完成回调complete中输出的是200,并不会和我们预期进入到error方法中来。

    3.原因

    用一句话来形容上面的问题就是:ajax异步请求A,A内部重定向到B。
    得到的答案是:
    1.ajax回调方法success中得到是B页面内容
    2.ajax是用于处理数据的,并不会按照服务器的内部跳转而进行跳转,如果要跳转可以根据回调中信息进行跳转。
    3.ajax请求,后端出现跳转,不会进入到error回调中的,当然回调中跳转到一个不存在的页面,那是会进入error方法中来的。
    当服务器将302响应发给浏览器时,浏览器并不是直接进行ajax回调处理,而是先执行302重定向,回调success中获取的内容是重定向后的页面。
    jquery源码中是这样写的,http状态码200-300或者304才会进入success回调的
    isSuccess = status >= 200 && status < 300 || status === 304;//确定请求是否成功

    // Cache response headers
    responseHeadersString = headers || "";
    
    // Set readyState
    jqXHR.readyState = status > 0 ? 4 : 0;
    
    // Determine if successful
    isSuccess = status >= 200 && status < 300 || status === 304;
    
    // Get response data
    if ( responses ) {
        response = ajaxHandleResponses( s, jqXHR, responses );
    }
    
    // Convert no matter what (that way responseXXX fields are always set)
    response = ajaxConvert( s, response, jqXHR, isSuccess );
    
    // If successful, handle type chaining
    if ( isSuccess ) {
    
        // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
        if ( s.ifModified ) {
            modified = jqXHR.getResponseHeader("Last-Modified");
            if ( modified ) {
                jQuery.lastModified[ cacheURL ] = modified;
            }
            modified = jqXHR.getResponseHeader("etag");
            if ( modified ) {
                jQuery.etag[ cacheURL ] = modified;
            }
        }
    
        // if no content
        if ( status === 204 || s.type === "HEAD" ) {
            statusText = "nocontent";
    
        // if not modified
        } else if ( status === 304 ) {
            statusText = "notmodified";
    
        // If we have data, let's convert it
        } else {
            statusText = response.state;
            success = response.data;
            error = response.error;
            isSuccess = !error;
        }
    } else {
        // We extract error from statusText
        // then normalize statusText and status for non-aborts
        error = statusText;
        if ( status || !statusText ) {
            statusText = "error";
            if ( status < 0 ) {
                status = 0;
            }
        }
    }
    

    4.如何处理ajax异步请求后端跳转

    ajax异步请求数据,后端出现跳转,这个时候说明程序出现了异常,可以捕获到这个异常,返回给前端,前端ajax根据返回信息,进行判断,给出正确的提示。
    在全局异常中可以这样返回给前端

                actionExecutedContext.Result = new JsonResult()
                {
                    Data = new ViewModels.Web.Response.JsonResultModel()
                    {
                        code = 302,
                        message = "具体的错误信息",
                        success = false
                    }
                };
    

    前端可以进行判断,给出相应的提示信息或者直接跳转

    $.ajax({
        url: '/User/Add',
        type: 'post',
        data: data,
        success:function(data,status)
        {
          if(code==302)
          {
            alert(data.message);
            //location.href='/User/Login' 也可以在返回类型加一个字段location,那就直接location.href='/User/Login/'
          }
    	    console.log('data:'+data);
       	    console.log('status:'+status);
        },
        complete: function(xhr){
            console.log(xhr.status);
        },
        error: function (xhr) {
       		debugger;
            console.log(xhr.status);
        }
    });    
    

    5.总结

    1.ajax success回调处理,具体状态码为 status >= 200 && status < 300 || status === 304
    2.ajax是用于异步获取数据的,并不是用于页面跳转
    3.mvc中,如果给某些方法设置权限,就会导致权限验证,从而产生跳转登陆界,应该加上全局的异常捕获,既然是ajax请求,说明请求数据出现异常,应该给出相应的错误信息提示,这个提示也应该在服务器进行确定,前端负责展示。
    4.ajax异步请求中,服务器不应该出现直接跳转。

  • 相关阅读:
    Pandas绘图不支持中文解决方案
    MVC模式
    解决import javafx.geometry.Point2D无法导入的问题
    初学linux时遇到的那些哭笑不得的问题
    啊啊我找不到web.xml怎么办呀~~
    解决JSP调用JavaBean出现乱码问题
    设置eclipse自动补全
    ubuntu下eclipse java ee首次打开提示找不到jdk的问题
    android webview 报 [ERROR:in_process_view_renderer.cc(189)] Failed to request GL process. Deadlock likely: 0 问题
    ubuntu创建文件夹桌面快捷方式
  • 原文地址:https://www.cnblogs.com/zhangmumu/p/10624771.html
Copyright © 2020-2023  润新知