(四) DWR JS工作流程

 

DWR工作流程簡單來說,

例子中jsp中引入/DWRDemo/dwr/interface/dwrDate.js文件中,方法都是調用 _execute方法,框架封裝了_sendData發送ajax請求,後臺返回JS代碼,前端解析,在調用_remoteHandleCallback方法,執行我們寫的回調方法;

dwrDate.getYear = function(callback) {
  dwr.engine._execute(dwrDate._path, 'dwrDate', 'getYear', callback);
}
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <!-- 這三個js導入項必不可少 -->
    <!-- 每一個對象都會有以一個對象爲名稱的那個js庫 -->
    <!-- Dwr 引擎庫 -->
      <script type='text/javascript' src='/DWRDemo/dwr/engine.js'></script>
      <!-- Dwr 工具庫 -->
      <script type='text/javascript' src='/DWRDemo/dwr/util.js'></script>
	 <script type="text/javascript" src="/DWRDemo/dwr/interface/dwrDate.js"></script>
    <script>
        window.onload = function(){            
            dwrDate.getYear(function(data){
               
                document.getElementById("showTime").innerHTML += 1900 + data + " 年 ";
            });
            dwrDate.getMonth(function(data){
                document.getElementById("showTime").innerHTML += 1 + data + " 月 ";
            });
        };

    </script>
</head>
<body>
<div id="showTime">當前時間:</div>

</body>
</html>

記錄下我今天分析的代碼:

1.singleShot我理解爲一個控制批量發送請求的標誌位,true表示不批量發送;
2.arguments參數爲方法傳入的參數
3.所有_execute()方法入參由dwr自動生成,最後一個參數默認爲回調的方法,存儲在callData的callback屬性中,也會保存在handlers[0]的callback屬性裏,後面回調就是調的這個callback

4.傳遞的參數中包含這樣的參數

c0-scriptName=dwrDate
c0-methodName=getYear
c0-id=0

不使用批量發送的話每次參數都以c0-開頭,因爲每次發送都會new一個新的batch對象,callCount都會從0開始重新增加

 

dwr.engine._execute = function(path, scriptName, methodName, vararg_params) {
  var singleShot = false;
  if (dwr.engine._batch == null) {
    dwr.engine.beginBatch();
    singleShot = true;
  }
  var batch = dwr.engine._batch;
  // To make them easy to manipulate we copy the arguments into an args array
  var args = [];
  for (var i = 0; i < arguments.length - 3; i++) {
    args[i] = arguments[i + 3];
  }
  // All the paths MUST be to the same servlet
  if (batch.path == null) {
    batch.path = path;
  }
  else {
    if (batch.path != path) {
      dwr.engine._handleError(batch, { name:"dwr.engine.multipleServlets", message:"Can't batch requests to multiple DWR Servlets." });
      return;
    }
  }
  // From the other params, work out which is the function (or object with
  // call meta-data) and which is the call parameters
  var callData;
  var lastArg = args[args.length - 1];
  if (typeof lastArg == "function" || lastArg == null) callData = { callback:args.pop() };
  else callData = args.pop();

  // Merge from the callData into the batch
  dwr.engine._mergeBatch(batch, callData);
  batch.handlers[batch.map.callCount] = {
    exceptionHandler:callData.exceptionHandler,
    callback:callData.callback
  };

  // Copy to the map the things that need serializing
  var prefix = "c" + batch.map.callCount + "-";
  batch.map[prefix + "scriptName"] = scriptName;
  batch.map[prefix + "methodName"] = methodName;
  batch.map[prefix + "id"] = batch.map.callCount;
  for (i = 0; i < args.length; i++) {
    dwr.engine._serializeAll(batch, [], args[i], prefix + "param" + i);
  }

  // Now we have finished remembering the call, we incr the call count
  batch.map.callCount++;
  if (singleShot) dwr.engine.endBatch();
};

createBatch之後singleShot已經變爲true,進入endBatch方法:

endBatch()方法

首先進行了一些校驗工作,dwr.engine._batch不能爲空、batch.map.callCount不能爲零,如果傳入了參數options,options是個對象,支持參數有:rpcType、 httpMethod、async、timeout、errorHandler,、warningHandler、textHtmlHandler,請求消息頭、方法參數等,這樣可以實現局部的個性化,其他方法調用不會引起誤會。_ordered屬性是用來控制是否嚴格按照順序來發送請求得到響應;通過_sendData(batch)發送ajax請求。

 

dwr.engine.endBatch = function(options) {
  var batch = dwr.engine._batch;
  if (batch == null) {
    dwr.engine._handleError(null, { name:"dwr.engine.batchNotBegun", message:"No batch in progress" });
    return;
  }
  dwr.engine._batch = null;
  if (batch.map.callCount == 0) return;

  // The hooks need to be merged carefully to preserve ordering
  if (options) dwr.engine._mergeBatch(batch, options);

  // In ordered mode, we don't send unless the list of sent items is empty
  if (dwr.engine._ordered && dwr.engine._batchesLength != 0) {
    dwr.engine._batchQueue[dwr.engine._batchQueue.length] = batch;
  }
  else {
    dwr.engine._sendData(batch);
  }
};

sendData方法太佔篇幅就不貼代碼了;

_sendData方法主要就是ajax發送請求,置於推送模式,暫時沒能力分析,ajax異步請求狀態改變事件爲dwr.engine._stateChange(); 接收到響應類似這樣;通過

if (toEval != null) toEval = toEval.replace(dwr.engine._scriptTagProtection, "");
 dwr.engine._eval(toEval);

eval函數調用了eval()方法來解析響應的JS字符串,並執行該方法dwr.engine._remoteHandleCallback,裏面就會執行我們寫入的回調函數了

throw 'allowScriptTagRemoting is false.';
//#DWR-INSERT
//#DWR-REPLY
dwr.engine._remoteHandleCallback('0','0',118);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章