`

(三)AJAXPro之旅---原理的探究

阅读更多

前面2篇文章我介绍了AJAXPro的一些实际应用.但是其基本的原理还不是很清楚,感觉做技术的,
最好还是"知其然知其所以然",这样才可以做到"有的放矢".

现在我们从头开始,了解AJAXPro的处理方式.

首先,我们在Web.config中添加了一段httpHandler注册.

<add path="*.ashx" verb="*" type="AjaxPro.AjaxHandlerFactory,AjaxPro.2"/>

这样,所有以ashx结尾的文件都由AjaxPro.AjaxHandlerFactory这个httpHandler处理.

打开使用AJAXPro注册的页面(就是使用AjaxPro.Utility.RegisterTypeForAjax(typeof(页面类))的页面).
查看其代码:发现他添加了4段js代码:

<script type="text/javascript" src="/ajaxpro/prototype.ashx"></script>
<script type="text/javascript" src="/ajaxpro/core.ashx"></script>
<script type="text/javascript" src="/ajaxpro/converter.ashx"></script>
<script type="text/javascript" src="/ajaxpro/SD2007.Test.Test1,SD2007.ashx"></script>
prototype.ashx就是prototype.js.一个著名的js开源AJAX框架.(地球人都知道吧!)
core.ashx是什么呢?
他其实就是一个js的类,这个类的作用是创建XMLHttpRequest对象进行异步操作.还有,XMLHttpRequest是依赖于浏览器的.
如果浏览器不能创建,则创建一个IFrameXmlHttp类来进行异步操作,也就是创建一个iframe.
converter.ashx是一个转换对象,用来把.Net数据类型转换到js中使用.前面一篇我的函数返回的是一个Hashtable 对象,但
他则转换成2维的数组.这个对象可以转换很多的.net数据类型.
SD2007.Test.Test1,SD2007.ashx就是我们页面注册AJAXPro对象产生的文件,他的代码不长,如下:
if(typeof SD2007 == "undefined") SD2007={};
if(typeof SD2007.Test == "undefined") SD2007.Test={};
SD2007.Test.Test1_class 
= function() {};
  Object.extend(SD2007.Test.Test1_class.prototype, Object.extend(
new AjaxPro.AjaxClass(), {
    GetCity: 
function(sName) {
      return this.invoke("GetCity", {"sName":sName}, this.GetCity.getArguments().slice(1));
    },
    url: '
/ajaxpro/SD2007.Test.Test1,SD2007.ashx'
}));
SD2007.Test.Test1 
= new SD2007.Test.Test1_class();
他利用prototype建立对象,并"继承"对象AjaxPro.AjaxClass,扩展一个GetCity方法,这个方法invoke调用ASP.Net里
注册为AJAXPro.Method的
GetCity方法.也就是异步操作的核心.他其实也是利用其他的js框架来实现异步数据的操作,不
过"异步的调用一个方法"而已.
我们现在看看其invoke方法的实现(红色的注释是我自己添加上去的):
invoke: function(method, args, callback, context) {
        
this.__start = new Date().getTime();

        
// if(this.xmlHttp == null) {
            this.xmlHttp = new XMLHttpRequest();  //建立异步对象

        
// }

        
this.isRunning = true;
        
this.method = method;
        
this.args = args;
        
this.callback = callback;
        
this.context = context;
        //是否使用异步操作
        
var async = typeof(callback) == "function" && callback != AjaxPro.noOperation;
        
        
if(async) {
            
if(MS.Browser.isIE) {
                
this.xmlHttp.onreadystatechange = this.doStateChange.bind(this);
            } 
else {
                
this.xmlHttp.onload = this.doStateChange.bind(this);
                
this.xmlHttp.onerror = this.mozerror.bind(this);
            }
            
this.onLoading(true);
        }
        
        
var json = AjaxPro.toJSON(args) + "";  //转换成JSON数据
        //下面做什么的不知道,好像是用了加密数据的
        if(AjaxPro.cryptProvider != null && typeof AjaxPro.cryptProvider.encrypt == "function")     {
            json 
= AjaxPro.cryptProvider.encrypt(json);
        }
        
        
this.xmlHttp.open("POST"this.url, async);  //post数据
        
this.xmlHttp.setRequestHeader("Content-Type""text/plain; charset=utf-8");
        
this.xmlHttp.setRequestHeader("X-" + AjaxPro.ID + "-Method", method);
        
        
if(AjaxPro.token != null && AjaxPro.token.length > 0) {
            
this.xmlHttp.setRequestHeader("X-" + AjaxPro.ID + "-Token", AjaxPro.token);
        }

        
/* if(!MS.Browser.isIE) {
            this.xmlHttp.setRequestHeader("Connection", "close");
        } 
*/
        //超时处理
        
this.timeoutTimer = setTimeout(this.timeout.bind(this), AjaxPro.timeoutPeriod);
        //发送数据
        
trythis.xmlHttp.send(json); }catch(e){}    // IE offline exception

        
if(!async) {
            
return this.createResponse({error: null,value: null});
        }

        
return true;    
    }
};
发现就是js调用XMLHttpRequest对象,然后发生数据进行异步操作而已.不过加了其他的一些他的代码.不过其中的

doStateChange函数比较的重要,他将会在服务端返回后执行.

doStateChange: function() {
        
this.onStateChanged(this.xmlHttp.readyState, this);
        
if(this.xmlHttp.readyState != 4 || !this.isRunning) {
            
return;
        }
        
this.duration = new Date().getTime() - this.__start;
        
if(this.timeoutTimer != null) {
            clearTimeout(
this.timeoutTimer);
        }
        
var res = this.getEmptyRes();
        
if(this.xmlHttp.status == 200 && this.xmlHttp.statusText == "OK") {
            res 
= this.createResponse(res);
        } 
else {
            res 
= this.createResponse(res, true);
            res.error 
= {Message:this.xmlHttp.statusText,Type:"ConnectFailure",Status:this.xmlHttp.status};
        }
        
        
this.endRequest(res);
    },

 如果 status 是 200,也就是 OK,那么清除掉超时处理函数,最后使用 callback 调用 createResponse 函数
还记得如果不是异步的话,createResponse 将会直接调用而不是通过 doStateChange 吧。

下面我们继续看看createResponse函数

createResponse: function(r, noContent) {
        
if(!noContent) {
            
if(typeof(this.xmlHttp.responseText) == "unknown") {
                r.error 
= {Message: "XmlHttpRequest error reading property responseText.", Type: "XmlHttpRequestException"};
                
return r;
            }
            
var responseText = "" + this.xmlHttp.responseText; 
            //解密数据
            
if(AjaxPro.cryptProvider != null && typeof AjaxPro.cryptProvider.decrypt == "function") {
                responseText 
= AjaxPro.cryptProvider.decrypt(responseText);
            } 

            
if(this.xmlHttp.getResponseHeader("Content-Type"== "text/xml") {
                r.value 
= this.xmlHttp.responseXML;
            } 
else {
                
if(responseText != null && responseText.trim().length > 0) {
                    r.json 
= responseText;
                    
var v = null;
                    eval(
"v = " + responseText + ";");
                    
if(v != null) {
                        
if(typeof v.value != "undefined") r.value = v.value;
                        
else if(typeof v.error != "undefined") r.error = v.error;
                    }
                }
            }
        }
        
/* if(this.xmlHttp.getResponseHeader("X-" + AjaxPro.ID + "-Cache") == "server") {
            r.isCached = true;
        } 
*/
        //返回响应的数据
        
return r;
    } 


如果前面的 json 也就是 Request 是加过密的,这里就需要对 responseText 进行解密。完了之后得到 r.value,r 将会被返回并提供给 callback 函数。r 被传入它的 res 参数。整个 Ajax ClientScript 的流程就差不多是完成了。

AJAXPro大概原理的探究已经差不多了,看完了他的实现,我才发现js真的是一个很"强悍"的语言.学好了,在web开
发上将会如虎添翼.

下篇介绍:(四)AJAXPro之旅---AJAXPro类库的探索...

(特补上IFrameXmlHttp的分析(加了注释了):)

AjaxPro.IFrameXmlHttp.prototype = {
    onreadystatechange: 
null, headers: [], method: "POST", url: null, async: true, iframe: null,
    status: 
0, readyState: 0, responseText: null,
    abort: 
function() {
    },
    readystatechanged: 
function() {
        
var doc = this.iframe.contentDocument || this.iframe.document;
        
if(doc != null && doc.readyState == "complete" && doc.body != null && doc.body.res != null) {
            
this.status = 200;
            
this.statusText = "OK";
            
this.readyState = 4;
            
this.responseText = doc.body.res;    //设置响应文本为IFrame的documnet的内容
            this.onreadystatechange();
            
return;
        }
        setTimeout(
this.readystatechanged.bind(this), 10);
    },
    open: 
function(method, url, async) {
        
if(async == false) {
            alert(
"Synchronous call using IFrameXMLHttp is not supported.");
            
return;
        }
        
if(this.iframe == null) {
            
var iframeID = "hans";
            
if (document.createElement && document.documentElement &&
                (window.opera 
|| navigator.userAgent.indexOf('MSIE 5.0') == -1))
            {
                
//建立iframe
                var ifr = document.createElement('iframe');
                ifr.setAttribute('id', iframeID);
                ifr.style.visibility 
= 'hidden';    //隐藏iframe
                ifr.style.position = 'absolute';
                ifr.style.width 
= ifr.style.height = ifr.borderWidth = '0px';

                
this.iframe = document.getElementsByTagName('body')[0].appendChild(ifr);   //添加到body
            }
            
else if (document.body && document.body.insertAdjacentHTML)
            {
                
//也是建立iframe,考虑到浏览器兼容性
                document.body.insertAdjacentHTML('beforeEnd', '<iframe name="' + iframeID + '" id="' + iframeID + '" style="border:1px solid black;display:none"></iframe>');
            }
            
//设置iframe变量为刚才建立的iframe DOM对象
            if (window.frames && window.frames[iframeID]) {
                
this.iframe = window.frames[iframeID];
            }
            
this.iframe.name = iframeID;
            
this.iframe.document.open();
            
this.iframe.document.write("<"+"html><"+"body></"+"body></"+"html>");
            
this.iframe.document.close();
        }
        
this.method = method;
        
this.url = url;
        
this.async = async;
    },
    
//建立响应头
    setRequestHeader: function(name, value) {
        
for(var i=0; i<this.headers.length; i++) {
            
if(this.headers[i].name == name) {
                
this.headers[i].value = value;
                
return;
            }
        }
        
this.headers.push({"name":name,"value":value});
    },
    getResponseHeader: 
function(name, value) {
        
return null;
    },
    
//建立input ,如果数据有回车则建立textarea
    addInput: function(doc, form, name, value) {
        
var ele;
        
var tag = "input";
        
if(value.indexOf("\n">= 0) {
            tag 
= "textarea";
        }
        
        
if(doc.all) {
            ele 
= doc.createElement("<" + tag + " name=\"" + name + "\" />");
        }
else{
            ele 
= doc.createElement(tag);
            ele.setAttribute(
"name", name);
        }
        ele.setAttribute(
"value", value);
        form.appendChild(ele);
        ele 
= null;
    },
    send: 
function(data) {
        
if(this.iframe == null) {
            
return;
        }
        
var doc = this.iframe.contentDocument || this.iframe.document;
        
var form = doc.createElement("form");
        
//建立一个form.设置其参数
        doc.body.appendChild(form);
        
        form.setAttribute(
"action"this.url);
        form.setAttribute(
"method"this.method);
        form.setAttribute(
"enctype""application/x-www-form-urlencoded");
        
        
for(var i=0; i<this.headers.length; i++) {
            
switch(this.headers[i].name.toLowerCase()) {
                
case "content-length":
                
case "accept-encoding":
                
case "content-type":
                    
break;
                
default:
                    
this.addInput(doc, form, this.headers[i].name, this.headers[i].value);
            }
        }
        
//建立input ,如果数据有回车则建立textarea
        this.addInput(doc, form, "data", data);
        form.submit();    
//提交数据
        
        setTimeout(
this.readystatechanged.bind(this), 0);
    }
};

 


 

分享到:
评论

相关推荐

    AjaxPro使用说明 - lexus - 博客园

    AjaxPro使用说明 - lexus - 博客园 Ajax是异步Javascript和XML(Asynchronous JavaScript and XML)的英文缩写。"Ajax"这个名词的发明人是Jesse James Garrett,而大力推广并且使Ajax技术炙手可热的是Google。Ajax的...

    AjaxPro.2.dll

    - **Bin**:这个目录包含了所有应用程序依赖的编译后的DLL文件,包括AjaxPro.2.dll,以及可能的其他第三方库。 通过研究这些文件,你可以了解如何在ASP.NET Web2.0环境中集成和使用AjaxPro来构建高效、响应式的Web...

    ajaxpro原理机制探讨(含有源码)

    在本文中,我们将深入探讨AjaxPro的工作原理、机制以及源码分析。 **一、AjaxPro的工作原理** 1. **异步通信**:AjaxPro利用XMLHttpRequest对象进行异步通信。当用户触发一个Ajax请求时,JavaScript代码会创建一个...

    AjaxPro入门实例之用户验证

    AjaxPro是一种基于ASP.NET的JavaScript库,用于创建高度交互性和响应式的Web应用程序。它通过使用异步技术,如...通过学习和实践,开发者能够更好地理解AjaxPro的工作原理,并能创建出更加流畅、用户友好的应用程序。

    AjaxPro文件及使用文档

    AjaxPro是一种基于JavaScript和.NET Framework的库,它扩展了AJAX(Asynchronous JavaScript and XML)技术,使得开发者能够创建高性能、交互性强的Web应用程序。在Web开发中,AjaxPro允许服务器端代码(通常是C#或...

    JS Ajax --- 使用AjaxPro 调用后台方法 操作数据库

    在IT领域,特别是Web开发中,Ajax(Asynchronous JavaScript and XML)技术的引入极大地提升了用户界面的...通过理解上述原理和实践,开发者可以更加熟练地掌握AjaxPro的使用,提升其在实际项目中的应用效率和效果。

    vs 2005 ajaxpro 2.0

    在本文中,我们将深入探讨AjaxPro 2.0的关键特性、工作原理以及如何在Visual Studio 2005环境中进行集成和应用。 **1. AjaxPro 2.0 概述** AjaxPro是基于AJAX(Asynchronous JavaScript and XML)技术的.NET框架,...

    AjaxPro

    1. **学习成本**:虽然AjaxPro简化了Ajax开发,但学习和掌握其API和工作原理仍需要一定的时间。 2. **资源消耗**:由于其强大的功能,AjaxPro可能比一些轻量级的Ajax库消耗更多的服务器和客户端资源。 3. **版本...

    AjaxPro 简单Demo适合初学者

    AjaxPro是一款基于JavaScript和.NET Framework的库,它使得在ASP.NET环境中实现Ajax功能变得更加简单。这个"AjaxPro简单Demo适合初学者"是一个很好的起点,帮助新手理解如何在实际项目中运用AjaxPro技术来提升Web...

    Asp.net AjaxPro实现

    #### AjaxPro的引入及其工作原理 **1. 引入AjaxPro** AjaxPro是用于ASP.NET的一个框架,旨在简化Ajax的使用,使得服务器端的.NET方法能够直接被客户端的JavaScript调用。要使用AjaxPro,首先需要在项目中引用...

    ajaxPro的简单使用

    AjaxPro是.NET框架下的一种实现页面无刷新技术的库,它允许开发者在ASP.NET应用程序中创建AJAX(Asynchronous JavaScript and XML)功能,提供类似JavaScript库如jQuery的体验,但与服务器端的.NET代码更紧密集成。...

    AjaxPro Demo

    通过这些实例,你可以深入理解AjaxPro的工作原理和最佳实践,学习如何在自己的项目中有效地应用AjaxPro。 总的来说,AjaxPro Demo是学习和掌握AjaxPro的宝贵资源,通过这些示例,开发者能够快速上手,并在实际开发...

    AjaxPro实现页面异步更新

    AjaxPro是针对ASP.NET平台设计的一个强大的AJAX框架,它允许开发者在不刷新整个页面的情况下实现部分页面的异步更新,提升...通过理解并掌握AjaxPro的工作原理和使用方法,开发者可以显著提高项目的质量和用户体验。

    ajaxpro源码和应用说明

    这个压缩包包含的"ajaxpro源码"提供了深入理解AjaxPro工作原理和定制功能的宝贵资源。 **AjaxPro的基本概念:** 1. **服务器端组件封装**:AjaxPro能够将ASP.NET控件和自定义方法封装成AJAX可调用的对象,使得...

    AjaxPro新组件

    在本文中,我们将深入探讨AjaxPro的相关知识点,包括其工作原理、主要特性、使用方法以及与传统AJAX技术的对比。 1. **AjaxPro的工作原理** AjaxPro通过在客户端和服务器端之间进行JSON或XML数据交换来实现无刷新...

    AjaxPro三级联动

    AjaxPro的工作原理是,它在客户端创建了一个模拟的ASP.NET Page生命周期的对象,允许你在JavaScript中调用服务器端的方法,就像它们是在同一个页面上一样。服务器端的方法执行完毕后,结果会被序列化并回传到客户端...

    商业编程-源码-AjaxPro入门实例之用户验证.zip

    这个压缩包“商业编程-源码-AjaxPro入门实例之用户验证.zip”包含了一个具体的示例,帮助开发者理解如何在实际项目中应用AjaxPro进行用户验证。 AjaxPro的核心功能是实现异步JavaScript和XML(AJAX)技术,使得网页...

    AjaxPro.dll

    AjaxPro.dll是Ajax.NET Professional框架的核心组件,它是一个强大的JavaScript库,用于在ASP.NET应用程序中实现无刷新的用户界面和异步数据交换。这个库的主要目的是提升Web应用的用户体验,通过减少页面完全刷新的...

    AjaxPro源码学习资料

    AjaxPro是一种基于JavaScript的库,主要用于创建高性能、交互性强的Web应用程序。它通过异步通信技术,即Ajax(Asynchronous JavaScript and XML),使得网页能够不刷新整个页面的情况下更新部分内容,提高了用户...

Global site tag (gtag.js) - Google Analytics