ajax The sequence diagram below details the participants on both the client and server needed to provide an AJAX progress bar. The details are explained in further detail in the remainder of this document. Tracking the progress of a server-side operation by a client requires two operations which include: Now let us review each of these operations in more detail. Negotiate a Task Id An HTML form button The On the server, a servlet The snippet of code from the The The On the client, the response from the This Polling Loop The polling loop polls the The In the code above, the Upon receiving the response from the The HTML DOM is updated by Progress Bar Using AJAX: Design Details
onClick
event calls a JavaScript function which in turn will create an XMLHttpRequest
object and the URL and callback function as may be seen in the JavaScript code snippet below. function submitTask() {
var url = "task?action=startTask";
var bttn = window.document.getElementById("taskbutton");
bttn.disabled = true;
initRequest(url);
// set callback function
req.onreadystatechange = processInitialRequest;
req.send(null);
}
function initRequest(url) {
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
isIE = true;
req = new ActiveXObject("Microsoft.XMLHTTP");
}
req.open("GET", url, true);
}url
in the code above includes a URL parameter action
which is set to "startTask." When the req.send(null);
statement is executed the request is sent to the URL "task" The client continues processing page events because the interaction is configured to be an asynchronous HTTP GET with the req.open("GET", url, true);
statement. TaskServlet
is mapped to the URL "task." When the TaskServlet receive a request containing a parameter "action" with the value of "startTask," a new Task
is created as can be seen in the code snippet below. if ((action != null) && action.equals("startTask")) {
// this task will take 15 cycles of the counter to complete
Task t = new Task(counter, 15);
taskCounter++;
tasks.put(taskCounter + "", t);
// return intial content
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
PrintWriter pw = response.getWriter();
pw.write("<message&qt;" + taskCounter + "</message>");
pw.flush();
}TaskServlet
above shows the TaskServlet
creating a new Task
object and placing it in a java.util.HashMap
with a unique identifier. For this example, an int
taskCounter
is used to identify each Task
. taskCounter
increments each time a new Task
is created. In cases where the progress will be tracked in an environment outside the firewall, more unique identifiers may be necessary to prevent nefarious user from tracking operations they did not initiate. taskCounter
is the unique id that is returned to the XMLHttpRequest
in an XML document. This id is later used to track the progress of the Task
when the client polls the TaskServlet
. In this example, the TaskServlet
has an internal timer running on a thread which sleeps for 2 seconds and increments the variable counter
. To simulate a server-side operation this example sets the Task
duration be 15 increments of the counter
(30 seconds total). TaskServlet
is received by the XMLHttpRequest
object which calls the processIntialRequest()
callback function shown below. // callback function for intial request to schedule a task
function processInitialRequest() {
if (req.readyState == 4) {
if (req.status == 200) {
var item = req.responseXML.getElementsByTagName("message")[0];
var message = item.firstChild.nodeValue;
// the initial requests gets the targetId
targetId = message;
messageHash = 0;
window.status = "";
createProgressBar();
showProgress(0);
}
var idiv = window.document.getElementById("task_id");
idiv.innerHTML = "Task ID=" + targetId;
// do the initial poll in 2 seconds
setTimeout("pollTaskmaster()", 2000);
}
}processInitialRequest()
function extracts the task id from the XML document and assigns it to the variable targetId
. The function will then initialize the progress bar in the HTML DOM and and show the initial progress of 0. The statement setTimeout("pollTaskmaster()", 2000);
is then executed to start the polling loop. TaskServet
using the task id store in the targetId
variable until the server-side operation is completed (a response of 100 is returned). function pollTaskmaster() {
var url = "task?messageHash=" + escape(messageHash) + "&targetId=" + targetId;
initRequest(url);
req.onreadystatechange = processPollRequest;
req.send(null);
}pollTaskmaster()
function configures the XMLHttRequest object with a URL and callback function. The request is sent to the URL "task" which is mapped on the server to the TaskServlet
. The following code in the TaskServlet
is responsible for processing the request. int percentage = 0;
if (tasks.get(targetId) != null) {
percentage = ((Task)tasks.get(targetId)).getPrecentComplete(counter);
}
if ((messageHash !=null) &&
(Integer.valueOf(messageHash).intValue()) == percentage) {
// nothing has changed
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
} else {
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
PrintWriter pw = response.getWriter();
if (percentage &qt; 100) percentage = 100;
pw.write("
pw.flush();
}Task
object is looked up using the unique id (targetId
) provided in the request. The Task getPrecentComplete
method is called with the current counter
to calculate the progress of the operation and the results are returned in an XML document. Note that if the messageHash
representing the current percentage of completion being displayed by the client matches the percentage complete of the operation in the Task
(indicating no change) the TaskServlet
will return an HTTP response code 304
(No Content
). This saves time for post processing of the message by the client, time for message generation by the TaskServlet
, and bandwidth for transmitting the message. TaskServlet
the XMLHttpRequest
object will call the processPollRequest()
to do post processing of the request. function processPollRequest() {
if (req.readyState == 4) {
if (req.status == 200) {
var item = req.responseXML.getElementsByTagName("message")[0];
var message = item.firstChild.nodeValue;
showProgress(message);
messageHash = message;
} else {
window.status = "No Update for " + targetId;
}
if (messageHash < 100) {
setTimeout("pollTaskmaster()", 5000);
} else {
setTimeout("complete()", 2500);
}
}
}showProgress()
function if the req.status
HTTP status code is 200
. This function will detect if the percentage from the server is complete (100) and stop the polling loop by calling the complete()
function. Otherwise, the polling will continue to loop by executing the setTimeout("pollTaskmaster()", 5000);
statement following a 5 second delay.
Progress Bar Using AJAX: Design Details
80酷酷网 80kuku.com