關於 XMLHttpRequest對象的onreadyStateChange方法


最近做了一個Ajax的demo,前台用HTML+javascript,后台用一個servlet來響應,流程如下:

頁面點擊鏈接事件,由js捕獲,生成一個請求到后台,servlet處理后給出響應信息,並顯示在頁面上。

 

問題是,頁面無法獲取到servlet的響應信息。

 

初始代碼

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Test H2</title>
    <style>
        #result{
            position:absolute;
            left:50px;
            top:300px;
        }
    </style>
    <!-- <script type="text/javascript" src="js/jquery-1.11.1.js"></script> -->
    <script>
        function handle(url){
            // Fetch the data, HERE i just give some dummy data
            var username = "joshua";
            var query = "query_test";
            var feature = url;
            var click_type = "clc_test";
            var rank = 1;
            var page_number = 1;
            var paras = "?query="+query+"&username="+username+"&feature="+feature+
                        "&click_type="+click_type+"&rank="+rank+"&page_number="+page_number;
            // transfer this data to servlet to save
            var xmlhttp;
            // code for IE7+, Firefox, Chrome, Opera, Safari
            if(window.XMLHttpRequest){
                xmlhttp = new XMLHttpRequest;
            // code for IE6, IE5
            }else{
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.open("POST","/WebDemo_H2/AjaxServlet"+paras+"&tip="+Math.random(),true);
            xmlhttp.send();
        document.getElementById("result").innerHTML = xmlhttp.responseText;
        }
    </script>
</head>
<body>
    <aside style="margin:10px;">
        <div>
            <p style="font-weight:bold;">Main Testing Page</p>
            <a href="index.html">Back</a>
        </div>
        <div style="height:20px"></div>
        <div>
            <a href="javascript:handle('test1.html')">test link 1</a><br/>
            <a href="javascript:handle('test2.html')">test link 2</a><br/>
            <a href="javascript:handle('test3.html')">test link 3</a>
        </div>
    </aside>
    <button onclick="">Clear Data</button>
    <div id="result">
    </div>
</body>
</html>

Servlet:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AjaxServlet extends HttpServlet {

    public Connection conn = null;

    public void init() {
        try {
            Class.forName("org.h2.Driver");
            conn = DriverManager.getConnection(
                    "jdbc:h2:C:/Users/zhoum18/H2Test/db/test", "sa", "");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
            request.setCharacterEncoding("GBK");
            response.setContentType("text/html;charset=GBK");
        // get the parameters
        try {
            PrintWriter out = response.getWriter();
            String userName = request.getParameter("username");
            String query = request.getParameter("query");
            String feature = request.getParameter("feature");
            String click_type = request.getParameter("click_type");
            String rank = request.getParameter("rank");
            String page_number = request.getParameter("page_number");
            String sql = "INSERT INTO CLICK_TRACKING SELECT ?,?,?,?,?,?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, query);
            pstmt.setString(2, userName);
            pstmt.setString(3, feature);
            pstmt.setString(4, click_type);
            pstmt.setInt(5, Integer.parseInt(rank));
            pstmt.setInt(6, Integer.parseInt(page_number));
            pstmt.executeUpdate();
            conn.commit();

            sql = "select feature,count(*) as num  from click_tracking group by feature";
            pstmt = conn.prepareStatement(sql);
            ResultSet rs = pstmt.executeQuery();
            out.println("<table border='1'>");
            out.println("<tr>");
            out.println("<td>Link</td>");
            out.println("<td>Click Times</td>");
            out.println("</tr>");
            while (rs.next()) {
                out.println("<tr>");
                out.println("<td>" + rs.getString("feature") + "</td>");
                out.println("<td>" + rs.getString("num") + "</td>");
                out.println("</tr>");
            }
            out.println("</table>");
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void destroy() {
        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {
            }
        }
    }
}

可以看到在servlet中用PrintWriter對象返回了建立table的HTML語句,按照邏輯,應該在頁面上打印出table的內容跟應有的值;

結果是,xmlhttp.responseText方法返回的值始終為空,沒有任何值返回,用chrome瀏覽器調試,發現HTTP請求是有響應的,而且response tab里面有值:

 

 

經過代碼查看,發現xmlhttp對象的readystate始終為1.

修改了下頁面js的代碼,將原有的寫入改成了以下代碼:

            xmlhttp.open("POST","/WebDemo_H2/AjaxServlet"+paras+"&tip="+Math.random(),true);
            xmlhttp.onreadystatechange = function(){
                if (xmlhttp.readyState == 4) {
                    document.getElementById("result").innerHTML = xmlhttp.responseText;
                }
            }
            xmlhttp.send();

成功顯示出response的內容。

 

結論:

頁面發送出請求后,往往無法得知什么時候才能完成這個請求並獲得回應,所以要使用一個事件機制來捕獲請求完成的狀態。

XmlHttpRequest對象有一個方法,onreadystatechange這個函數實現這一個功能。

類似於回調函數,在readystate改變時,這個方法可以指定一個函數來判斷和處理,比如上面的代碼:

xmlhttp.onreadystatechange = function(){

  // 這里面的就是當readystate改變時,處理事件的代碼,在我的例子中,判斷了當readyState等於4的時候,再捕獲相應的信息。

}

 

readyState的不同值,代表了不同的狀態:

0:尚未初始化
1:正在加載
2:加載完畢
3:正在處理
4:處理完畢

當其變為4, 就可以訪問從服務器返回的數據了。

另附http請求相應代碼

200 請求成功
202 請求被接受但處理未完成
400 錯誤請求
404 請求資源未找到
500 內部服務器錯誤

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM