关于Ajax的那些事儿

Ajax作为WEB中一个重要的异步交互方式,其作用就不需要我在这里强调了,关于它的使用,我在项目中还是遇到了一些问题的,在这里我把它列出来,希望能够帮到大家。

出现的Bug:
1. Ajax无法解析从后台传过来的json数据
2. 后台报错了Ajax依然走了success方法
Bug复现:
Ajax无法解析从后台传过来的json数据
原始数据
解析json数据失败
源码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%  String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + 
        request.getServerPort() + path + "/";   
%>
<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
<title>Insert title here</title>
</head>
<body>
    <form action="test/ajaxTest" method="post">
        姓名:<input type="text" id="account" name="account"/>
        密码:<input type="password" id="passcode" name="passcode"/>
        <input type="submit" value="提交"/>
    </form>
</body>
<script type="text/javascript">
    $(document).ready(function() {
        $("form").submit(function() {
            var form = $(this);
            $.ajax({
                type: form.attr('method'),
                url: form.attr('action'),
                data:{
                    account: $("input[name=account]").val(),
                    passcode: $("input[name=passcode]").val()
                },
                dataType: "json",
                success: function (data){
                    alert("原始json数据:" + data);
                    eachTest(data);
                },
                error: function(){
                    alert("Network Error..." );
                }
            });
            return false;
        });
        function eachTest(data) {
            var json = data;
            //var json = eval("(" + data + ")");
            alert("获取json属性:json.account:" + json.account);
            $.each(json,function(key,value){
                alert(key + ": " + value);
            });
        }

    });
</script>
</html>  

关键在于最后的一个方法

    function eachTest(data) {
        var json = data;  
        //var json = eval("(" + data + ")");  
        alert("获取json属性:json.account:" + json.account);  
        $.each(json,function(key,value){  
        alert(key + ": " + value);  
        });  
    }

实际上从后台服务器获取的并不是json格式的数据,而是满足json格式的字符串,因此并不能直接当做
json来使用,直接对其进行解析的话就会解析不出来,需要对其转换

function eachTest(data) {
    //var json = data;  
    var json = eval("(" + data + ")");  
    alert("获取json属性:json.account:" + json.account);  
    $.each(json,function(key,value){  
    alert(key + ": " + value);  
    });  
}  

转换之后的效果:
解析json数据正常
这里简单说明一下Ajax关键方法的意思

$.ajax({
    type:   //这里填写的是ajax的提交方式,比如:"post","get"
    url:  //需要提交请求的地址,比如"https://www.google.com",  
            "user/userAction"
    data: //需要提交的数据,注意,是提交给服务器的数据
    dataType:  //服务器返回的的数据类型,比如"String","json"等
    contentType:  //ajax的上下文类型,如
                    "application/x-www-form- urlencoded"(有时候解析不
                    到json数据也可能是因为页面的cententType和表单/ajax的不
                    一致导致的,具体可以打开调试 -- network -- 选择页面 --Responce Headers这一栏(需要刷新一遍网页才会显示))
    success:  //表明ajax与后台连接成功后走的方法,可以有从后台返回的数据参数这
                里需要注意的是只要ajax与后台建立联系,就会走success方法,即使
                没有从后台获取到有用的数据,这里会有逻辑bug,下边有讲
    error:  //ajax与后台连接失败走的方法,一般会由于网络连接失败,但是也会有其他
                原因导致走error这个方法,比如你的url找不到,没有数据data
});

查看contentType示例:
查看contentType示例
关于Ajax与后台建立完整连接以上的内容就可以满足

接下来我要讲讲关于使用Ajax编程的程序严谨性问题(在上边的程序片段注释中也提到过)

我们知道Ajax中的success方法是在ajax与后台服务器创建完整连接之后就会走的方法,并且可以返回从后台获取到的反馈数据,但是,这个反馈的数据是不是一定是我们需要的呢?能够获取到后台反馈数据,那是在后台程序执行正常的情况下才能成功,但是后台如果出现bug,那么你的ajax依旧执行了success方法,由于没有得到你需要的参数,所以你的页面是没有任何反馈(或者是动作)的

Bug复现:
后台报错了Ajax依然走了success方法

html>
<head>
    <title>Struts Problem Report</title>
    <style>
        pre {
            margin: 0;
            padding: 0;
        }    
    </style>
</head>
<body>
    <h2>Struts Problem Report</h2>
    <p>
    Struts has detected an unhandled exception:
    </p>


<div id="exception-info">
<table>
    <tr>
        <td><strong>Messages</strong>:</td>
        <td>
            <ol>
                        <li>Connection refused: connect</li>
                        <li>Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.</li>
                        <li>Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.</li>
            </ol>
        </td>
    </tr>
    <tr>
        <td><strong>File</strong>:</td>
        <td>org/springframework/jdbc/datasource/DataSourceTransactionManager.java</td>
    </tr>
    <tr>
        <td><strong>Line number</strong>:</td>
        <td>245</td>
    </tr>

</table>
</div>


<div id="stacktraces">
<hr />
<h3>Stacktraces</h3>
<div class="stacktrace" style="padding-left: 0em">
    <strong>org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.</strong>
    <div>
    <pre>
    org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:245)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
    org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:439)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    com.sun.proxy.$Proxy9.queryOneInfo(Unknown Source)
    com.cs.action.UserAction.signupCheckAccount(UserAction.java:53)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:892)
    ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1537)
    ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
    com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117)
    com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108)
    ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1613)
    ognl.ASTMethod.getValueBody(ASTMethod.java:91)
    ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    ...... ......

这里是我从浏览器调试模块中截取的部分内容,大致意思是说数据库这一块出问题了,没有连接到数据库(因为我都没开数据库服务),这是我在做项目中偶然遇到的,一般我们的数据库服务器是一直开着的,但是我之前因为出门,就把电脑关了,数据库的服务顺带也关了,后来进行测试的时候,发现之前都没有动的程序怎么突然失灵了,然后在后台也没有看到bug,我以为是需要重启服务(应用程序服务,非数据库服务),但是重启之后还是没有用,程序检查了半天之后感觉没毛病,我就纳闷了,到底是哪里出了问题,我专门有对ajax的连接过程仔细检查了一遍,没毛病,我又专门写了个ajax的测试(没有使用到数据库),也没有毛病,这就尴尬了,这程序之前好好的,怎么现在就不听使唤了?然后我就抱着试试看的心态在浏览器调试中找找看,结果还真是找到了,原来是后台数据库方面除了bug,之前都没有往那边想,也没想去调试,毕竟后台都没有看到报错,其实这也奇怪,后台看不到报错,却能在浏览器中看到,有问题啊,不过总算找到问题来源了,这就好办了

关键来了,在这个过程中我们看到,即使你的ajax程序与后台创建了连接,也就是走了success方法,但是,这也并不能保证你能够从后台获取到你所需要的数据
可能很多人在使用ajax的时候根本就没有考虑到这个问题,以为走了success方法就算与后台创建连接了,也就自然而然的能够获取到自己所需要的信息(我之前也是这么认为的),那么今天看到这个例子,我想对大家编程的严谨性应该有一定的帮助

下边是我的对以上bug进行处理的代码(ajax部分):

$.ajax({
            type: "post",
            url: "user/signupCheckAccount",
            data:account.serialize(),
            dateType: "json",
            contentType: "application/x-www-form-urlencoded",
            cache: false,
            success: function(data){
                connectSuccess1(data)
            },
            error: function(){
                alert("Network error...");
            }
        });
function connectSuccess1(data){
        console.log(data);
        /*判断是否从后台获取到所需要的反馈数据,后台(主要是数据库)出故障仍然走succsee*/
            if(data.match("^\{(.+:.+,*){1,}\}$")){
                var flag = eval("(" + data + ")");
                $.each(flag,function(key,value){
                    if(key == "SIGNUPCHECKACCOUNT_FLAG" && value == "success"){
                        ... ... 
                    }else{
                        $('#input-account-msg').html("*该账号已经被注册!请重新输入!");
                        $('#input-account').focus().select();
                    }
                });
        }else{
            alert("亲,出了点小问题,请稍后再注册!");
            var location = (window.location+'').split('/');
            var basePath = location[0]+'//'+location[2]+'/'+location[3];
            var url = basePath + '/homepage.jsp';
            window.location.href = url;
        }
    }

以上代码是我在写注册的时候用的,主要是用来从数据库检测用户输入的账号是否已经存在,对于以上出现的问题,我的处理办法(程序已经很明显了,我在啰嗦一遍)是先检查返回的数据是不是自己想要的,如果不是,说明后台肯定哪里是崩了,然后就不需要这么进行下去了,直接跳走,如果是,那就就请继续

以上就是我在ajax方面遇到的问题以及解决方案,希望对大家有帮助!

猜你喜欢

转载自blog.csdn.net/mrqiang9001/article/details/61614415