JS之AJAX-进度事件

通常情况下,使用readystatechange事件监听HTTP请求的完成。XHR2规范草案定义了进度事件Progress Events事件,XHR对象在请求的不同阶段触发不同类型的事件,所以不再需要检测readyState属性,该规范定义了客户端与服务端通信的有关事件。这些事件最早其实只针对XHR操作,但目前也被其他API(如File API)借鉴。

事件

loadstart: 在接收到响应数据的第一个字节时触发

progress: 在接收到响应期间持续不断的触发

error: 在请求发生错误时触发

abort: 在调用abort()方法终止连接使触发

load: 在接收到完整的响应数据时触发

loadend: 在通信完成,或者触发error、abort、load事件时触发

timeout: 在请求超时使触发

每个请求都从loadstart事件开始,接着每个50ms左右触发一次progress事件,然后触发error、abort、load或timeout事件中的一个,最后以触发loadend事件结束

对于任何请求,浏览器将只会触发error、abort、load或timeout事件中的一个。XHR2规范草案指出一旦这些事件中的一个发生后,浏览器应该触发loadend事件

注意: IE9-浏览器不支持以上事件(IE9浏览器仅支持load事件)

load事件

load事件会在响应接收完毕时触发,因此不用再去检查readyState属性了。但是请求完成不代表请求成功,所以还会使用XHR对象的status属性判断是否请求成功

xhr.onload = function(e) {
  if(xhr.status == 200) {
    console.log(xhr.responseText);
  }
}

progrerss

progress事件会在接收到响应期间持续不断的触发,触发期间会接收到一个event对象,包含着四个属性:target属性是XHR对象、lengthComputable是一个表示进度信息是否可用的布尔值、loaded表示已经接收的字节数、total表示根据Content-Length响应头部确定的预期字节数。

下面是一个音乐文件的加载过程示例

<div id="result"></div>
  <div id="music"></div>
  <button id="btn">btn</button>
  <script>

  btn.onclick = function() {
    var xhr = new XMLHttpRequest();
    xhr.onprogress = function(e) {
      if(e.lengthComputable) {
        result.innerHTML = e.loaded  + 'bytes / ' + e.total + 'bytes';
      }
    }
    xhr.onload = function(e) {
      var data = xhr.response;
      if(xhr.status == 200) {
        var audio = document.createElement('audio');
        audio.onload = function() {
          URL.revokeObjectURL(audio.src);
        }
        audio.src = URL.createObjectURL(data);
        audio.setAttribute('controls', '');
        if(!music.innerHTML) {
          music.appendChild(audio);
        }
      }
    }
    xhr.open('GET', '/pfzl.mp3', true);
    xhr.responseType = 'blob';
    xhr.send();
  }
</script>

上传进度

XHR2定义了XMLHttpRequest对象的upload属性,用于监控HTTP请求的上传事件。该属性的属性值是一个对象,它定义了addEventListener()方法和整个Progress Events事件集合

可以像使用progress事件处理程序一样使用upload事件处理程序。对于XMLHttpRequest对象,设置XHR.onprogress可以监控响应的下载进度,设置XHR.upload.onprogress可以监控请求的上传进度

下面是一个上传进度的示例

<input type="file" name="file" id="uploadInput" style="display: none;">
<div id="progress"></div>
<div id="result"></div>
<button id="btn">upload</button>
<script>

btn.onclick = function() {
  uploadInput.click();
}
uploadInput.onchange = function() {
  var file = uploadInput.files[0];
  var xhr = new XMLHttpRequest();
  xhr.upload.onprogress = function(e) {
    if(e.lengthComputable) {
      progress.innerHTML = e.loaded  + 'bytes / ' + e.total + 'bytes';
    }
  }
  xhr.onload = function(e) {
    if(xhr.status == 200) {
      if(!result.innerHTML) {
        result.innerHTML = xhr.responseText;
      }
    }
  }
  xhr.open('POST', '/api/test', true);
  xhr.setRequestHeader('Content-Type', file.type);
  xhr.send(file);
}

其他事件

当HTTP请求无法完成时会有三种情况,对应三种不同的事件:

  1. 如果请求超时,会触发timeout事件
  2. 如果请求中止,会触发abort事件
  3. 网络错误会触发error事件

调用abort()方法可以取消正在进行的HTTP请求,该方法一旦调用,会触发abort事件。一个比较常见的应用场景,假如使用XMLHttpRequest为文本输入域请求自动完成推荐,如果用户在服务器的建议达到之前输入了新字符,这时等待请求不再有用,应该中止

XHR对象的timeout属性等于一个整数,表示多少毫秒后,如果请求仍然没有得到结果,就会自动终止并触发timeout事件。该属性默认等于0,表示没有时间限制

var xhr = new XMLHttpRequest();
btn.onclick = function(){
  xhr.abort();
};
xhr.ontimeout = function(){
  console.log('The request timed out.');
}
xhr.timeout = 100;
xhr.onabort = function(){
  console.log("The transfer has been canceled by the user.");
}
xhr.onerror = function(){
  console.log("An error occurred while transferring the file.");    
}
xhr.onloadend = function(){
  console.log("请求结束");    
}
posted @ 2021-09-29 14:17  wmui  阅读(435)  评论(0编辑  收藏  举报