编写高性能的JavaScript-Ajax数据传输之MXHR(4)

动态载入脚本

这个技术的特点克服了XHR最大的缺点:跨域访问。使用如下:

var scriptElement = document.createElement('script');

scriptElement.src = 'http://any-domain.com/javascript/lib.js';

document.getElementsByTagName('head')[0].appendChild(scriptElement);

动态载入脚本不像XHR那样可以随意设置请求头部,参数只能通过GET发送,只有脚本从服务器完全返回以后你才能访问脚本。

由于这种方式的响应结果是可执行的JS代码,不需要特殊的处理和分析,因而性能十分可观。不过你仍然需要注意,使用这种方式时你对服务器完全没有控制,你无法获得脚本载入期间的信息。而且你也要意识到动态载入的脚本一旦加载完成,它就能够对本页面的数据内容进行修改、转发或者重定向,所以使用时需要格外小心。

更多信息可以看这里:http://book.51cto.com/art/200812/99672.htm

Mulipart XHR

这个是以上Ajax请求数据几种方式中最新的技术。MXHR的特点是,只使用一个请求来从服务器将资源发送给客户端,只要组装好了不论是CSS文件、脚本文件、HTML片段还是base64编码的图片。客户端以字符串的形式接受,然后根据MIME类型和其它传输的信息来解析。

示例-使用一个请求下载多个图片资源:

var req = new XMLHttpRequest();

req.open('GET', 'rollup_images.php', true);

req.onreadystatechange = function() {

if (req.readyState == 4) {

splitImages(req.responseText);

}

};

req.send(null);

首先请求页面,然后将响应数据利用方法解析。当然这需要服务器首先要将图片信息转化为base64编码的字符串,同时你需要指定一个连接符号,以便在客户端分割这些字符串。

假定分割符是unidcode编码的1

function splitImages(imageString) {

var imageData = imageString.split("\u0001");

var imageElement;

for (var i = 0, len = imageData.length; i < len; i++) {

imageElement = document.createElement('img');

imageElement.src = 'data:image/jpeg;base64,' + imageData[i];

document.getElementById('container').appendChild(imageElement);

}

}

任何能够在JS中通过字符串处理的数据类型都可以使用这种方式传输。以下是几个常用函数:

function handleImageData(data, mimeType) {

var img = document.createElement('img');

img.src = 'data:' + mimeType + ';base64,' + data;

return img;

}

function handleCss(data) {

var style = document.createElement('style');

style.type = 'text/css';

var node = document.createTextNode(data);

style.appendChild(node);

document.getElementsByTagName('head')[0].appendChild(style);

}

function handleJavaScript(data) {

eval(data);

}

MXHR传输的数据越来越庞大时,最好的方式是接受一部分数据以后立刻开始处理,而不是等待全部数据加载完成再处理。通过监听XHRreadyState 3来处理。

var req = new XMLHttpRequest();

var getLatestPacketInterval, lastLength = 0;

req.open('GET', 'rollup_images.php', true);

req.onreadystatechange = readyStateHandler;

req.send(null);

function readyStateHandler{

if (req.readyState === 3 && getLatestPacketInterval === null) {

// Start polling.

getLatestPacketInterval = window.setInterval(function() {

getLatestPacket();

}, 15);

}

if (req.readyState === 4) {

// Stop polling.

clearInterval(getLatestPacketInterval);

// Get the last packet.

getLatestPacket();

}

}

function getLatestPacket() {

var length = req.responseText.length;

var packet = req.responseText.substring(lastLength, length);

processPacket(packet);

lastLength = length;

}

一旦readyState 3第一次触发,一个计时器启动。每隔15ms检测新数据,当找到一个事先约定的分隔符之后收集数据,然后处理这部分数据。

更完美的实现比较复杂但是值得研究,你可以看看这里:http://techfoolery.com/mxhr/

这个技术的缺点就是获取的数据你无法缓存,比如图片、CSS文件等;另外就是老版本的IE不支持监听readyState 3,也不支持dataURLs。(IE8支持,IE6IE7需要变通方法)

不过由于它的优点实在是吸引人,所以这些情况你最好使用MXHR

1)如果这个页面包含很多其他页面不需要的资源,尤其是图片;

2)如果站点的每个页面的脚本或CSS都已经组装为一个独特的请求,亦即站点内跨页面访问没有共同的请求。

减少HTTP请求能够全面提升页面的性能,尤其是你需要传输100张图片,只用一个请求通常能为站点的用户体验带来质的飞跃。测试页面:http://techfoolery.com/mxhr/

PS:content is from <High Performance JavaScript> by Nicolas Zakas

posted @ 2010-05-08 23:43  高凡凡高  阅读(480)  评论(0编辑  收藏  举报