XmlHttpRequest学习笔记 (8) ReadyState详解

上一篇,readyState的值有5种,具体说明如下:

0: XmlHttpRequest对象刚被创建出来,还未初始化,即open方法没有被调用过。此时,除了open和onreadystatechange之外,访问其它任何的方法或属性,都是无效的。原因显而易见。

1: HTTP请求已被创建,但还没有发送出去,即open已被调用过。这时候,访问xhr的属性,比如status,也是无效的,因为HTTP连接还没有建立。但是可以调用abort把HTTP请求重置,即回到0状态。

2: HTTP请求已发送,并且服务器已返回HTTP报头。此时,可以通过getResponseHeader来查看所需的HTTP报头

3: 收到服务器响应的内容。对于readyState = 3,readystatechange的回调方法可能会被调用多次。因为服务器可能会返回大量数据,使得客户端一次收不完。至于调用的频率,没有定数。由于一些限制,虽然已经得到了一部分的数据,但是responseText、responseStream和responseXML这些属性,依然是不能访问的。

4: HTTP通讯结束。此时所有的属性都可以访问了。如果所请求的数据不是XML格式的,responseXML将不会被初始化。此时调用abort也可以重置状态,但是没什么意义。

XmlHttpRequest学习笔记 (7) 异步模式

之前提到过,Open()方法的第三个参数Async指定了XmlHttpRequest的通信模式是同步的,还是异步的。当使用异步模式通信的时候,Send()方法会立即返回,而不会等到加载完所有服务器发回的数据才返回。在异步模式下,我们可以通过注册XmlHttpRequest的OnReadyStateChange回调函数来获取它状态的变化,从而做出相应的操作。

来看下面的代码:

这段代码中,当xhr对象的readyState有变化时,xhr会自动调用它的onreadystatechange所对应的方法,也就是那个匿名方法。readyState的值从0到4,分别代表了XmlHttpRequest的5种状态:

  1. 未初始化(Open方法未被调用)
  2. 请求已创建(Open方法已调用,Send方法未调用)
  3. 报头可用(Send方法已调用,并已获得HTTP报头)
  4. 交互中(XmlHttpRequest正在和服务器通信)
  5. 完成(XmlHttpRequest已加载所有数据)

使用异步模式,我们就可以在加载服务器数据的同时,做一些其它的事情,比如显示一个进度条什么的,来提高用户体验。

另外,在异步模式中,可以使用abort方法来中断HTTP请求。

XmlHttpRequest学习笔记 (6) 查看HTTP状态

HTTP状态是HTTP/1.1标准的一部分,它用数字的形式表示了HTTP通信所碰到的问题,比如:

  • 200:成功,即没有碰到任何问题;
  • 301:目标永久转移,以后的HTTP请求可直接发往新的地址;
  • 307:目标暂时转移;
  • 401:未授权,可能需要提供帐号信息;
  • 403:禁止,服务器拒绝响应这个请求;
  • 404:目标未找到;
  • 500:服务器内部错误;

详细的HTTP状态可以参考Wikipedia

在使用XmlHttpRequest做HTTP通信的时候,可以通过下面的属性来获取HTTP状态:

Status
StatusText

Status表示了数字形式的HTTP状态,而StatusText则是字符串形式的。下面是一个例子:

输出:

200 OK
404 Not Found

注意:在send()函数被调用之前,status和statusText是无法被访问的。

XmlHttpRequest学习笔记 (5) HTTP报头

HTTP报头(HTTP Header)是HTTP通信时的一些元数据(Metadata),用来让服务器和客户端达成一些共识,比如客户端的版本、通信内容的格式等。

在使用XmlHttpRequest时,也可以设置或读取HTTP报头,这时可以使用

setRequestHeader方法 和 getResponseHeader方法

先来看setRequestHeader(header, value)方法,它可以用来设置所发出的数据包的报头,比如

设置了Accept-Charset报头为UTF-8,也就是表明客户端支持UTF-8格式的内容,服务器为根据这个设置,来预处理响应的数据包。详细的HTTP报头的定义,可以参考RFC2616的第14节

和setRequestHeader相反,getResponseHeader(header)可用于查询服务器返回的数据包的报头:

假设value的值是"gzip",则说明服务器返回的内容,是使用gzip格式压缩的。

以下是一个样例:

输出为:

iPhone Content length = 30317
IE Content length = 63729

这就说明http://leonax.net/在响应不用的客户端时,返回的数据不一样。

顺便提一下,还有一个方法是getAllResponseHeaders(),可用于获取服务器返回的数据包中所有的报头。

顺便再提一下,一些影响安全性的报头,如Referrer和Content-Length,是不能使用setRequestHeader来设置的。

XmlHttpRequest学习笔记 (4) 解析Xml时的安全性

上一次我们说到XmlHttpRequest可以用来解析Xml,这样对解析网络中的Xml数据提供了很大的便利,不过也带来了一些问题。比如当Xml数据规模过大,就可能造成脚本运行速度慢,停止响应等问题……

碰到这种情况,我们可以使用responseXml中的一些属性来解决,比如

MaxElementDepth

这个属性可以控制需要解析的Xml数据的深度,比如形如<a><b/></a>的Xml的深度为2,如果此时MaxElementDepth所设置的值为1,XmlHttpRequest就会拒绝解析这个Xml,以达到防止客户端停止响应的目的。来看下面的代码:

由于设置了MaxElementDepth属性,responseXML会报告parseError: "系统错误: MaxElementDepth"

类似作用的属性还有:

  • ResolveExternals / AllowDocumentFunction:是否允许加载外部的Xml文件
  • AllowXsltScript:是否允许在XSLT运行自定义的Javascript脚本
  • MaxXMLSize:所允许最大的Xml文件的大小
  • ProhibitDTD:是否允许Xml中包含DTD (Document Type Definition)
需要注意的是,这些属性需要在send()之前设置,但是不能在open()之前设置,因为open()方法会在内部创建出responseXML对象;而send()方法被调用之后,就开始加载XML了,那时候再去设置,已经来不及了……

XmlHttpRequest学习笔记 (3) 解析Xml

和其它的http组件不同的是,XmlHttpRequest提供了自动的Xml解析:

responseXML方法

当服务器返回的数据是Xml格式的话,Xmlhttp会自动尝试用其自带的responseXML属性来解析它。responseXML实际上是一个IXMLDOMDocument对象,你可以使用IXMLDOMDocument所提供的方法来操作这个Xml。也就是说,当Xml解析出问题的时候,你可以使用responseXML.parseError来查询错误信息;否则就可以通过比如selectNodes之类的方法来查询Xml的内容。比如,下面的代码演示了如何查询leonax.net的RSS,并且打印出每一条blog的标题和链接:

输出结果如下:

试用传说中的ifttt @ http://leonax.net/p/3022/ifttt-trial/
三国杀——山扩展 @ http://leonax.net/p/3016/sanguosha-shan-ex/
China Joy 2011 @ http://leonax.net/p/3011/china-joy-2011/
在PowerShell中获取当前运行脚本的路径 @ http://leonax.net/p/3005/getting-location-of-executing-script-in-powershell/
美少女特攻队 Sucker Punch 2011 @ http://leonax.net/p/3000/sucker-punch-2011/
个人博客在国内的访问加速 @ http://leonax.net/p/2997/acceleration-of-personal-blog-from-mainland/
iPhone 5,我们能期待些什么? @ http://leonax.net/p/2989/what-can-we-expect-in-iphone-5/
学车笔记 (二) 倒桩 @ http://leonax.net/p/2986/notes-for-driving-study-2/
活埋 Buried 2010 @ http://leonax.net/p/2983/buried-2010/
美少女的谎言 Pretty Little Liars 2010 @ http://leonax.net/p/2979/pretty-little-liars-2010/

msxml3a.dll是干什么用的?

msxml3a.dll是MSXML 3.0的一个资源文件,提供了ANSI版本的资源(如错误信息等),与之对应的是msxml3r.dll,它提供了Unicode版本的资源。在近几代的Windows中(如Windows 7),msxml3a.dll已经被移除了,在System32文件夹下,只留下了msxml3.dll和msxml3r.dll。

需要MSXML3a.dll的原因,大概是在Windows 95/98的年代,Unicode还不是那么流行(或者还不支持),Windows的组件也多数基于ANSI来开发。Windows 9x被淘汰之后,基于NT的系统都是支持Unicode的,于是资源文件也就从ANSI变成了Unicode。

如果你在%SystemRoot%\System32下发现msxml3a.dll,那可能是一些比较老的应用程序,在安装包里内置了老版本的MSXML 3.0的文件,在安装的时候,由于msxml3.dll和msxml3r.dll被系统保护,无法覆盖,而msxml3a.dll则可以正常地复制到System32下,于是这个文件就出现了……同样的,你也可能看到msxml4a.dll,那是老版本的MSXML 4.0带来的。