异步监听readyState == 3

当readyState的值等于3时,此时服务器正在与浏览器传输数据,这个时候其实是可以进行获取到responseText值得,但是这个值并不完整,只有当readyState == 4时,值才是完整的。

但是如果我们需要获取的内容是极其长的字符,那么就可以通过监听这个状态,然后轮询的方式,可以在内容没有全部下载来之前就可以提前更新内容了,这样就可以避免在下载的过程中产生的等待时间。

var req = new XMLHttpRequest();
var getLastInterval =null,
    lastLength = 0;
req.open('GET','xxx.php',true);
req.onreadystatechange = readStateHandler;
req.send(null);

function readStateHandler() {
    if(red.readyStare == 3 && getLastInterval == null) {
        getLastInterval = setInterval(function(){
            getLastePacket();
        },15)
    }
    if(red.readyStare == 4) {
        clearInterval(getLastInterval);
        getLastePacket();
    }
}

function getLastePacket() {
    var length = req.responseText.length;
    var packet = req.responseText.substring(lastLength,length);
     callback(packet);
     lastLength = length;
}

当readyState等于3的时候,创建一个定时器,15ms调用一次getLastePacket函数,这个函数每次运行先得到当前req.responseText.length的字符长度,然后通过string的substring方法截取这段内容,然后下次运行的时候又从上一次的最后一个位置开始,然后回调函数callback,将packet字符串传入,这个回调函数还要根据你传入的值做判断,毕竟你需要判断目前的字符最后一项是否完整,如果不完整可以创建一个全局变量来保存,下次再续上。

通过这个方法可以在较大的内容时减少等待时间,增加用户体验。

multipart XHR

说白了就是通过php将多个地址合并成一个字符串返回给浏览器,浏览器通过js将返回的字符串解析成需要的值。

比如php返回三个img图片的地址,通过;分号连接。

if(req.readyState == 4) {
  splitImage(req.responsText);
}


function splitImage(text) {
  var imgelement = null,
      imgdata = text.split(';');
  for(var i =0,len = imgdata.length;i<len;i++){
      imgelement = document.createElement('img');
      imgelement.src = imgdata[i];
      document.getElementsByTagName('body')[0].appendChild(imgelement);
      
  }
}

以此类推,我们还可以增加更多的值,比如添加css地址,js文件,通过用不同的字符分隔,就可以判断到不同值,然后对应的获取。

发送数据

通过ajax发送数据其实有点奢侈,但是ajax支持pos方式发送,但是如果只是单方面的发送,且数据不会太大就可以使用get方式,但是ie对get方式的请求是有字符限制的,也就是说url的字符不能超过2048个字符,为此我要可以根据实际的使用情况使用对应的方法。

发送数据我们甚至可以使用动态插入script的方式,更深层的讲,我们是通过元素的src属性进行发送的。

这里暂时先不讲src的方式,这里完善一下ajax的方式

事实上我们还要考虑如果发送错误的话怎么处理,这里就要使用到error事件。

req.onerror = functuon() {
    //发生错误,我们在这个函数了再次调用封装的ajax函数,重新再运行一次,也就是递归
}

我们甚至可以使用setTimeout来增加延时机制,如果获取的数据是要等一段时间才能获取到,然后再发送给服务器,那么就可以onerror事件里面使用setTimeout。

get的方式会比post的方式发送更快,get只有一个数据包,而post至少会有两个,一个是头信息,一个是post数据。

Beacons

上面讲到发送数据使用的是src的属性,那么我们就可以通过图片的src属性来发送我们的数据,但是这个也有一点小问题,就是他会等待服务器返回信息,我们可以通过返回一个204 No Content状态码来阻止客户端继续等待返回的消息正文。

使用Beacons其实也是有限制的,他不能发送post请求,且url的长度是有限制的。

var url = 'xxx.php';
var parms = ['id=1','time=12578'];
var beacons = new Image();
beacons .src = url + '?' + parms.join('&');

beacons.onload = function() {
  //通过服务器返回一个图片,如果宽度是1表示成功,宽度为2表示错误
  if(beacons.width == 1) {
  
  }else if(beacons.width == 2) {
    
  }
}

beacons.onerror = function() {
  //如果发生错误,递归一次
}

数据的格式

XML的格式是以前比较通过的格式,但是太过于冗长,其内容书写和html类似,下面是一个标准的格式:

<?xml version="1.0" encoding='utf-8'>
<users total='2'>
  <user id="1">
    <username>alice</username>
    <realname>Alice Smith</realname>
    <email>alice@xxx.com</email>
  </user>
   <user id="2">
    <username>alice2</username>
    <realname>Alice Smith2</realname>
    <email>alice2@xxx.com</email>
  </user>
</users>

这种格式其实实质性的内容不多,为此并不是一种很好的方式,为此可以优化一下

<?xml version="1.0" encoding='utf-8'>
<users total='2'>
  <user id="1" username="alice" realname="Alice Smith" email="alice@xxx.com"/>
   <user id="2" username="alice2" realname="Alice Smith2" email="alice2@xxx.com"/>
</users>

通过属性值得方式可以将大量重复性的标签丢弃,从而减少文件的大小,并且js也可以更简便的获取内容。

JSON

json的格式相对于xml他更倾向于数据简化,因为json你不必要像xml那样写大量的标签,json他就是一个高度集中的数据格式。

那么json的优化,最简单的就是减少书写的内容,比如name的键名改为n,单个字符,或者直接省略,通过数组的方式直接保存内容,这种方式虽然对阅读不友好,但是只要按照一样的规定去写,就可以极大的提高json文件的解析和下载速度。

自定义格式

json虽然很好,但是如果文件内容庞大的话,还是有其他的优化方式,比如自定义的格式,我们可以在一个js文件里面保存一个对象,这个对象保存着自定义的string内容,然后内容之间通过字符分隔,比如不同的内容用:分号隔开,同一个分组的值多个的话用:冒号隔开,然后ajax获取或者动态script获取,由于是一个js文件,所以他没有json的解析步骤,这里就快于json了。

然后通过js的split()方法拆成分组,然后再针对每个组值再次详细拆分获取到需要的内容,最后保存在一个数组内并返回。

事实上split的速度是极快,在大量文本内容上快于json的parse。

缓存

ajax的get方式发出的请求才能被浏览器缓存,但这还不够,服务器还需要发送Expires 过期时间来控制缓存存在多久。

为此我们可以通过创建一个对象来保存获取到的信息,这种方式适用于同一个页面需要请求多次相同的内容。

分类: javascript高性能 标签: AJAX

评论

全部评论 1

  1. 爸爸
    爸爸
    Google Chrome Windows 10
    测试

目录