Prototype的源码分析

xiaoxiao2026-03-15  8

/**这个文件是对xmlhttp异步请求进行了简单的封装,*主要是将prototytp进行了简化,如果要使用复杂的功能可以使用prototype的ajax.js*外部使用时,主要调用方式为* var myAjax=new Ajax.Request(    url,    {    method: 'get',    asynchronous: true,    onSuccess: function(xmlHttp)    {           },    onFailure:function(xmlHttp){    },    onException:function(exception){    }    }   );    另可使用myAjax.header()和myAjax.evalResponse();   其他的都为内部调用函数,外部尽量不要使用。*/

/**基础函数*Class.create()*Try.these()*Object.extend()*Function.prototype.bind*/var Class = {   create: function() {     return function() {       this.initialize.apply(this, arguments);     }   }};var Try = {   these: function() {     var returnValue;

     for (var i = 0; i < arguments.length; i++) {       var lambda = arguments[i];       try {         returnValue = lambda();         break;       } catch (e) {}     }

     return returnValue;   }};var Abstract = new Object();Object.extend = function(destination, source) {   for (property in source) {     destination[property] = source[property];   }   return destination;};Function.prototype.bind = function(object) {   var __method = this;   return function() {     __method.apply(object, arguments);   }};/**基础ajax类*封装了一个函数:Ajax.getTransport()返回一个xmlhttp对象*这个类里的函数一般不使用。*/var Ajax = {     getTransport: function() {         return Try.these(             function() {return new ActiveXObject('Msxml2.XMLHTTP')},             function() {return new ActiveXObject('Microsoft.XMLHTTP')},             function() {return new XMLHttpRequest()}         ) || false;     }};/**基础ajax.base类*封装了三个函数:*setOptions:设置进行ajax请求的参数*responseIsSuccess:判断异步请求返回是否成功*responseIsFailure:判断异步请求返回是否失败*这个类里的函数也没有必要在实际中使用,只有在扩展是才会使用到*/Ajax.Base = function() {};Ajax.Base.prototype = {   setOptions: function(options) {     this.options = {       method:        'post',//异步请求方法,可以为get和post       asynchronous: true,   //设置是否为异步方式发送,       parameters:    ''      //传递参数,参数都是url编码格式a=valueOfA&b=valueOfB     }     Object.extend(this.options, options || {});//以上三个属性为异步请求的基本属性。   },   responseIsSuccess: function() {     return this.transport.status == undefined         || this.transport.status == 0          || (this.transport.status >= 200 && this.transport.status < 300);   },   responseIsFailure: function() {     return !this.responseIsSuccess();   }};

Ajax.Request = Class.create();/**定义了xmlhttp请求的状态。*0 (未初始化) 对象已建立,但是尚未初始化(尚未调用open方法) *1 (初始化) 对象已建立,尚未调用send方法 *2 (发送数据) send方法已调用,但是当前的状态及http头未知 *3 (数据传送中) 已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误, *4 (完成) 数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据 */Ajax.Request.Events =   ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];/**Ajax.Request对象,需要实例化对象,**/Ajax.Request.prototype = Object.extend(new Ajax.Base(),{   initialize: function(url, options) {     this.transport = Ajax.getTransport();//返回xmlhttp对象this.setOptions(options);//设置请求的参数,在初始化时写     this.request(url);//进行异步请求   },   request: function(url) {     var parameters = this.options.parameters || '';     if (parameters.length > 0) parameters += '&_=';

     try {       this.url = url;    /*如果是get方法的化,就将parameters里的内容添加到url里*/       if (this.options.method == 'get' && parameters.length > 0)         this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;       /*调用xmlhttp的请求函数,进行请求*/       this.transport.open(this.options.method, this.url,      this.options.asynchronous);

       /*如果是异步请求,对onreadystatechange绑定函数,对于为什么要用定时器,没10ms将状态设为Loading,我也没有明白。*/    if (this.options.asynchronous) {         this.transport.onreadystatechange = this.onStateChange.bind(this);         setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);       }   this.setRequestHeaders();//设置请求里的头部信息,包括编码等信息    /*对与post方式请求,也可以通过options里的postBody来设,这里就将postbody放到参数里进行传递*/       var body = this.options.postBody ? this.options.postBody : parameters;    /*发送post数据*/       this.transport.send(this.options.method == 'post' ? body : null);

     } catch (e) {       this.dispatchException(e);     }    },setRequestHeaders: function() {     var requestHeaders =   ['X-Requested-With', 'XMLHttpRequest'];

     if (this.options.method == 'post') {       requestHeaders.push('Content-type',          'application/x-www-form-urlencoded');

       /* Force "Connection: close" for Mozilla browsers to work around        * a bug where XMLHttpReqeuest sends an incorrect Content-length        * header. See Mozilla Bugzilla #246651.         */       if (this.transport.overrideMimeType)         requestHeaders.push('Connection', 'close');     }

     if (this.options.requestHeaders)       requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

     for (var i = 0; i < requestHeaders.length; i += 2)       this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);   },/**状态改变时,执行respondToReadyState,判断当状态为1时不执行。*/   onStateChange: function() {     var readyState = this.transport.readyState;     if (readyState != 1)       this.respondToReadyState(this.transport.readyState);   },/*   *返回异步请求返回文件的头部信息,name表示名字,函数返回参数值   */   header: function(name) {     try {       return this.transport.getResponseHeader(name);     } catch (e) {}   },   /*   *如果返回header信息里包括X-JSON/xxx,则会执行xxx的内容   *不是很明白这里,为什么要eval   */   evalJSON: function() {     try {       return eval(this.header('X-JSON'));     } catch (e) {}   },   /*   *很简单的函数,如果返回Content-type为text/javascript,则会调用此函数进行执行,我认为这处用途不大   */   evalResponse: function() {     try {       return eval(this.transport.responseText);     } catch (e) {       this.dispatchException(e);     }   },/*   *根据返回的状态决定该执行的步骤   */   respondToReadyState: function(readyState) {     var event = Ajax.Request.Events[readyState];     var transport = this.transport, json = this.evalJSON();

     if (event == 'Complete') {   /*   *此处如果状态处于完成状态则会进行分析分别调用onSuccess和onFailure,所以一般onComplete不调用为好   */       try {         (this.options['on' + this.transport.status]          || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]          || function(){})(transport, json);       } catch (e) {         this.dispatchException(e);       }       /*此处对返回js进行了eval*/       if ((this.header('Content-type') || '').match(/^text\/javascript/i))         this.evalResponse();     }         try {       (this.options['on' + event] || function(){})(transport, json);     } catch (e) {       this.dispatchException(e);     }         /* Avoid memory leak in MSIE: clean up the oncomplete event handler */     if (event == 'Complete')       this.transport.onreadystatechange = function(){};   },   /*   *错误时调用,一般外部使用onException:function(){}   */   dispatchException: function(exception) {     (this.options.onException || function(){})(this, exception);   }

   });

相关资源:Prototype源码浅析 Number部分
转载请注明原文地址: https://www.6miu.com/read-5045954.html

最新回复(0)