这二天用prototype.js中的ajax.request做了些东西,闲时看了下源码,体会如下:
在用AJAX部分前,有如下一些函数得了解一下:
Class变量


var
Class
=

{

create:
function
()

{


return
function
()

{

this
.initialize.apply(
this
, arguments);
}
}
}
initialize相当于构造器,和java的构造器一样,可以自定义为带参数性质的。prototype中很多对象都是用它来创建的,ajax也不例外。
Try.these() 方法


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;
}
}
它使得实现当你想调用不同的方法直到其中的一个成功正常的这种需求变得非常容易, 他把一系列的方法作为参数并且按顺序的一个一个的执行这些方法直到其中的一个成功执行,返回成功执行的那个方法的返回值。
ajax就是通过它得到一个可以跨borswer的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
;
}

activeRequestCount:
0
}
Object.extend方法:


Object.extend
=
function
(destination, source)

{


for
(property
in
source)

{
destination[property]
=
source[property];
}

return
destination;
}
顾名思义,可正扩展了一个对象属性列表。这样说可能不太明白,结合Ajax再下就清楚了,如下,


Ajax.Base.prototype
=

{

setOptions:
function
(options)

{


this
.options
=

{
method: 'post',
asynchronous:
true
,
parameters: ''
}

Object.extend(
this
.options, options
||

{}
);
}
,

}
可以看到在prototype中用ajax的时候,它的options默认有三个,默认值如上所示。这里可以通过以下方式来改变其默值(Ajax.Request的用法,呆会儿再看):

var
pars
=
'method
=
update
&
mbid
=
917
';

var
my
=
new
Ajax.Request(
uri,



{
method: 'post',
parameters: pars,
asynchronous:
false
,
}
);
}
这时有个问题可能不太好处理,假如想增加其它参数,怎么知道我所增加的参数是否符合prototype呢?确实!比如我想通过send方法传一段数据到后台,该用什么参数呢?在prototype中有如下代码:

var
body
=
this
.options.postBody
?
this
.options.postBody : parameters;

this
.transport.send(
this
.options.method
==
'post'
?
body :
null
);
可以看到应该是postBody,对于prototype中的参数以及其所代表的意义我想还是得通过源文件一个个的找。作者并没有初始一个集合(废话,不然也不要Object.extend方法了)。我觉得这个地方有待改进... ...
在send时方法一定要用post才能生效,这个时候parameters就会失效了,源码如下:

if
(
this
.options.method
==
'get'
&&
parameters.length
>
0
)

this
.url
+=
(
this
.url.match(
/
\
?/
)
?
'
&
' : '
?
')
+
parameters;
所以假如后台一定要一个parameter的话,比如若用到Struts的LookupDispatchAction就很可能要一个method参数。这时应该直接放到uri中去,最后要注意的一点就是用post的时候,一定要将响应头设置成Content-type==application/x-www-form-urlencoded. 好在prototype已经考虑到了这点:

this
.setRequestHeaders();
//
其具体代码可以看源文件

var
body
=
this
.options.postBody
?
this
.options.postBody : parameters;

this
.transport.send(
this
.options.method
==
'post'
?
body :
null
);
在这儿我说一下我在使用ajax过程中遇到乱码的解决方法:
从C到S头端时,在S端接到的是乱码解决分析过程。首先要明白AJAX内部是以utf-8来编码传输数据的。我们在页面所看到的数据都是按照我们自己预定的字符集解码所得到的。OK,现在假设我们在S端收到了来自C端的DATA为乱码,在C端(不管你的WEB页面是用什么编码方式)AJAX在其传输中把所传输的数据解码成UTF-8格式,到了S端后,我可能对所有请求方式都过滤编码,比如有如下设置:

<
filter
>

<
filter-name
>
encodingFilter
filter-name
>

<
filter-class
>
com.CharacterEncodingFilter

filter-class
>

<
init-param
>

<
param-name
>
encoding
param-name
>

<
param-value
>
GBK
param-value
>

init-param
>


filter
>
所以我们在S端看到的是将以UTF-8编码过的数据再以GBK解码后所得到的数据,这样乱码就出来了。所以解决也很简单,交其重新以自己的方式编码就OK了
new String(str.getBytes("gbk"),"utf-8");
同样的道理,假如在C端碰到的是乱码,那么在S端返回数据前将数据以UTF-8的格式传输
src.getBytes("UTF-8")
ajax.request中对事件的响应:
首先我们得在请求初始化中加入响应状态与自定义函数:

var
my
=
new
Ajax.Request(
url,



{
method: 'get',
parameters: pars,
asynchronous:
true
,
onComplete: showResponse
}
);
它初始化了一个ajax事件的集合

Ajax.Request.Events
=
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
这五个状态正好对应五个readystate,ajax的五个readystate分别如下:
0 (未初始化) 对象已建立,但是尚未初始化(尚未调用open方法)
1 (初始化) 对象已建立,尚未调用send方法
2 (发送数据) send方法已调用,但是当前的状态及http头未知
3 (数据传送中) 已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误,
4 (完成) 数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据
然后根据status(点这儿可以下载查看ajax参考资料,查看其所有属性)来触发指定事件,触发代码:


onStateChange:
function
()

{

var
readyState
=
this
.transport.readyState;

if
(readyState
!=
1
)

this
.respondToReadyState(
this
.transport.readyState);
}

respondToReadyState:
function
(readyState)

{

var
event
=
Ajax.Request.Events[readyState];



再次可以看到正好事件集合与readyState正好对应来调用,而通过以下来调用WEB自定义函数showResponse()


try

{
(
this
.options['on'
+
event]
||
Prototype.emptyFunction)(transport, json);
Ajax.Responders.dispatch('on'
+
event,
this
, transport, json);

}
catch
(e)

{

this
.dispatchException(e);
}
未完,待续...
本文详细解读了Prototype.js中Ajax.request的内部工作原理,包括`initialize`构造器、`Try.these`方法、`Object.extend`扩展对象、Ajax对象的`getTransport`和`send`方法,以及如何处理乱码和事件响应。重点讨论了参数管理、事件触发与响应机制以及跨浏览器xhr实现。
110

被折叠的 条评论
为什么被折叠?



