From Gossip@caterpillar

Ajax Gossip: 進度列

如果伺服端收到客戶端請求後,必須處理一段時間可以有回應,這時也許可以在客戶端設計一個進度列,顯示目前伺服端對於請求處理的進度,方式就是讓客戶端定時以非同步方式取得伺服端的請求進度,並以進度列顯示在網頁之上。

在這邊舉個最簡單的例子,假設網頁中有個按鈕,按下去之後會作某些事:

  • ProgressBarEX-1.html
<!DOCTYPE html PUBLIC 
"-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=BIG5">
<title>進度列</title>
<script type="text/javascript" src="ProgressBarEx-1.js"></script>
</head>
<body>

<input id="do" type="button" value="作某事XD" onclick="doSomething();">
<br/><br/>

<div id="progressbar"></div>

</body>
</html>

ProgressBarEx-1.js中在按下按鈕後,會暫時鎖定按鈕無法使用,並定時向伺服端取得進度,進度列是一個1像素寬、20像素高的圖片,藉由改變它在網頁中顯示的寬度來模擬進度列的增長:
  • ProgressBarEx-1.js
var xmlHttp;

function createXMLHttpRequest() {
if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else if(window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}

function doSomething() {
document.getElementById("do").disabled = true;
pollProgress();
}

function pollProgress() {
var url = "ProgressServlet?timeStamp=" + new Date().getTime();
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET", url);
xmlHttp.send(null);
}

function handleStateChange() {
if(xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
var percent = xmlHttp.responseXML.getElementsByTagName(
"percent")[0].firstChild.data;

var progressbar = document.getElementById("progressbar");
progressbar.innerHTML =
"<img src='images/ProgressBarEx-1.jpg' style='width:"

+ percent + "px; height: 20px;'><br/>" + percent + "%";

if(percent != 100) {
// 每兩秒查詢一次進度
setTimeout(pollProgress, 2000);
}
else {
document.getElementById("do").disabled = false;
}
}
}
}

伺服端必須傳回以下的XML格式表示進度:
<response>
    <percent>10</percent>
</response>

您可以搭配下面這個超級簡單的Servlet來摸擬伺服端的進度處理:

  • ProgressServlet.java
package onlyfun.caterpillar;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

import javax.servlet.http.*;

// 超級簡單的Servlet,只是用來測試客戶端的Progress bar orz..
public class ProgressServlet extends HttpServlet {
private int counter;

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

PrintWriter out = response.getWriter();
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
out.println("<response>");
out.println("<percent>");
out.println(10 * counter++);
out.println("</percent>");
out.println("</response>");
out.close();

if(counter > 10) {
counter = 0;
}
}
}