javascript性能优化(7)

Ajax 异步 JavaScript 和 XML

Ajax 是高性能 JavaScript 的基石。它可以通过延迟下载大量资源使页面加载更快。它通过在客户端和服 务器之间异步传送数据,避免页面集体加载。它还用于在一次 HTTP 请求中获取整个页面的资源。通过选 择正确的传输技术和有效的数据格式,你可以显著改善用户与网站之间的互动。

数据传输

有5种常用的技术用于向服务器请求数据:

  1. XMLHttpRequest (XHR)
  2. Dynamic script tag insertion 动态脚本标签插入
  3. iframes
  4. Comet
  5. Multipart XHR 多部分的 XHR
    现在常使用的三种技术是XHR、动态脚本标签插入、多部分的 XHR ;剩余两种就不做讨论。

XMLHttpRequest

    var url = '/data.php';
    var params = ['id=934875', 'limit=20'];
    var req = new XMLHttpRequest();
    req.onreadystatechange = function () {
     if (req.readyState === 3) { // Some, but not all, data has been received.     
             // Process the data here... 
         }
        else if (req.readyState === 4) {
            var responseHeaders = req.getAllResponseHeaders(); // Get the response headers.     
            var data = req.responseText; // Get the data.     
            // Process the data here...   
        }
    }
    req.open('GET', url + '?' + params.join('&'), true);
    req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // Set a request header. 
    req.send(null); // Send the request.

readyState 等于3 “ ”,表示此时正在与服务器交互,响应报文还在传输中。这就是所谓的“流”,他是提高数据请求性能的强大工具。readyState 等于4,表示整个响应报文已经收并完,可用于操作。

使用 POST,还是 GET

如果请求不改变服务器状态只是取回数据,则用get;get请求被缓冲起来,如果你多次提取相同的数据可提高性能。
只有当URL和参数的长度超过了2048个字符时才使用POST提取数据;因为IE限制URL的长度,过长将导致请求参数被截断。

动态脚本标签插入

    var scriptElement = document.createElement('script');
    scriptElement.src = 'http://any-domain.com/javascript/lib.js';
    document.getElementsByTagName('head')[0].appendChild(scriptElement);

在lib.js文件中,将调用jsonCallback函数组装数据;

     function jsonCallback(jsonString) {
        var data = ('(' + jsonString + ')');
        // Process the data here... 
    }

    jsonCallback({"status": 1, "colors": ["#fff", "#000", "#ff0000"]});

Multipart XHR 多部分XHR

多部分 XHR(MXHR)允许你只用一个 HTTP 请求就可以从服务器端获取多个 资源。它通过将资源(可以是 CSS 文件,HTML 片段,JavaScript 代码,或 base64 编码的图片)打包成一 个由特定分隔符界定的大字符串,从服务器端发送到客户端。JavaScript 代码处理此长字符串,根据它的 媒体类型和其他“信息头”解析出每个资源.

由于 MXHR 响应报文越来越大,有必要在每个资源收到时立刻处理,而不是等待整个响应报文接收完 成。这可以通过监听 readyState 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 第一次发出时,启动了一个定时器。每隔 15 毫秒检查一次响应报文中的新数据。数据片 段被收集起来直到发现一个分隔符,然后一切都作为一个完整的资源处理.

缺点:

  • 资源不能被浏览器缓存。
  • 老版本的 Internet Explorer 不支持 readyState 3 或 data: URL。Internet Explorer 8 两个都支 持,但在 Internet Explorer 6 和 7 中必须设法变通。

发送数据

当使用 XHR 将数据发回服务器时,它比使用 GET 要快。这是因为对少量数据而言,向服务器发送一个 GET 请求要占用一个单独的数据包。另一方面,一个 POST 至少发送两个数据包,一个用于信息头。另一 个用于 POST 体。POST 更适合于向服务器发送大量数据,即因为它不关心额外数据包的数量,又因为 Internet Explorer 的 URL 长度限制,它不可能使用过长的 GET 请求。

数据格式

这里只看了JSON,JSONP;其他的像XML等,不做分析。
常见的json格式

[   
 {"id":1, "username":"alice", "realname": "Alice Smith", "email":"alice@alicesmith.com"},
 {"id":2, "username":"bob", "realname": "Bob Jones", "email":"bob@bobjones.com"}, 
 {"id":3, "username":"carol", "realname": "Carol Williams","email":"carol@carolwilliams.com"},  
 {"id":4, "username":"dave", "realname": "Dave Johnson", "email":"dave@davejohnson.com"} 
] 

数组格式的json

[  
 [ 1, "alice", "Alice Smith", "alice@alicesmith.com" ],
 [ 2, "bob", "Bob Jones", "bob@bobjones.com" ],  
 [ 3, "carol", "Carol Williams", "carol@carolwilliams.com" ],  
 [ 4, "dave", "Dave Johnson", "dave@davejohnson.com" ] 
] 

数组形式的 JSON 在每一项中均获胜,它文件尺寸小,下载快,平均解析时间短。尽管解析函数 不得不遍历列表中所有 5’000 个单元,它还是快出了 30%。
避免使用 JSON-P的原因:因为 JSON-P 必须是可执行的 JavaScript,它使用动态 脚本标签注入技术可在任何网站中被任何人调用。从另一个角度说,JSON 在运行之前并不是有效的 JavaScript,使用 XHR 时只是被当作字符串获取。不要将任何敏感的数据编码为 JSON-P,因为你无法确定 它是否包含私密信息,或者包含随机的 URL 或 cookie。

数据格式总结

总的来说越轻量级的格式越好,好是 JSON 和字符分隔的自定义格式。如果数据集很大或者解析时间 成问题,那么就使用这两种格式之一:

  • JSON-P 数据,用动态脚本标签插入法获取。它将数据视为可运行的 JavaScript 而不是字符串,解析速度 极快。它能够跨域使用,但不应涉及敏感数据。
  • 字符分隔的自定义格式,使用 XHR 或动态脚本标签插入技术提取,使用 split()解析。此技术在解析非常 大数据集时比 JSON-P 技术略快,而且通常文件尺寸更小。
    这里写图片描述
    下载和解析时间对比。

Ajax 性能向导

缓存数据

快的 Ajax 请求就是你不要用它。有两种主要方法避免发出一个不必要的请求:
1. 在服务器端,设置 HTTP 头,确保返回报文将被缓存在浏览器中。
2. 在客户端,于本地缓存已获取的数据,不要多次请求同一个数据。
第一种技术容易设置和维护,而第二个给你大程度的控制。

设置 HTTP 头

在发起请求时使用 GET 方法。但这还不充分, 你必须在响应报文中发送正确的 HTTP 头。Expires 头告诉浏览器应当缓存响应报文多长时间.。其值是一个 日期,当过期之后任何对该 URL 发起的请求都不再从缓存中获得,而要重新访问服务器。一个 Expires 头 如下:
Expires: Mon, 28 Jul 2014 23:30:00 GMT
Expires 头中的日期是 GMT 日期。它在 PHP 中使用如下代码设置:

 $lifetime = 7 * 24 * 60 * 60; // 7 days, in seconds. 
 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $lifetime) . ' GMT'); 
 //这将告诉浏览器缓存此数据 7 天。

本地存储数据

除了依赖浏览器处理缓存之外,你还可以用手工方法实现它,直接存储那些从服务器收到的响应报文。 可将响应报文存放在一个对象中,以 URL 为键值索引它。这是一个 XHR 封装,它首先检查一个 URL 此 前是否被取用过,如果有直接调取之前的缓存;没有的话,就重新获取。

 var localCache = {};
    function xhrRequest(url, callback) {   // Check the local cache for this URL.   
        if (localCache[url]) {
            callback.success(localCache[url]);
            return;
        }   // If this URL wasn't found in the cache, make the request.   
        var req = createXhrObject();
        req.onerror = function () {
            callback.error();
        };
        req.onreadystatechange = function () {
            if (req.readyState == 4) {
                if (req.responseText === '' || req.status == '404') {
                    callback.error();
                    return;
                }       // Store the response on the local cache.      
                localCache[url] = req.responseText;
                callback.success(req.responseText);
            }
        }
        ;
        req.open("GET", url, true);
        req.send(null);
    }

Summary 总结


  • 高性能 Ajax 包括:知道你项目的具体需求,选择正确的数据格式和与之相配的传输技术。
  • 作为数据格式,纯文本和 HTML 是高度限制的,但它们可节省客户端的 CPU 周期。XML 被广泛应用 普遍支持,但它非常冗长且解析缓慢。JSON 是轻量级的,解析迅速(作为本地代码而不是字符串),交 互性与 XML 相当。字符分隔的自定义格式非常轻量,在大量数据集解析时速度快,但需要编写额外的 程序在服务器端构造格式,并在客户端解析。
  • 当从页面域请求数据时,XHR 提供完善的控制和灵活性,尽管它将所有传入数据视为一个字符串, 这有可能降低解析速度。另一方面,动态脚本标签插入技术允许跨域请求和本地运行 JavaScript 和 JSON, 虽然它的接口不够安全,而且不能读取信息头或响应报文代码。多部分 XHR 可减少请求的数量,可在一次响应中处理不同的文件类型,尽管它不能缓存收到的响应报文。当发送数据时,图像灯标是简单和有效的方法。XHR 也可用 POST 方法发送大量数据。
    一些建议:

  • 减少请求数量,可通过 JavaScript 和 CSS 文件打包,或者使用 MXHR。
  • 缩短页面的加载时间,在页面其它内容加载之后,使用 Ajax 获取少量重要文件。
  • 确保代码错误不要直接显示给用户,并在服务器端处理错误。
  • 学会何时使用一个健壮的 Ajax 库,何时编写自己的底层 Ajax 代码。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值