Prototype的源码分析

/*
*这个文件是对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);
   }

   }
);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值