Page 247 - Web性能权威指南
P. 247
if(event.lengthComputable) {
var progress = (event.loaded / event.total) * 100; ➍
...
}
}
xhr.upload.addEventListener('progress', onProgressHandler); ➎
xhr.addEventListener('progress', onProgressHandler); ➏
xhr.send();
➊ 设置请求的超时时间为 5000 ms(默认无超时限制)
➋ 为请求成功注册回调
➌ 为请求失败注册回调
➍ 计算传输进度
➎ 为上传进度事件注册回调
➏ 为下载进度事件注册回调
无 论 load 和 error 中 的 哪 一 个 被 触 发 了, 都 代 表 XHR 传 输 的 最 终 状 态, 而
progress 事件则可能触发任意多次,这就为监控传输状态提供了便利:我们可以比
较 loaded 与 total 属性,估算传输完成的数据比例。
要估算传输完成的数据量,服务器必须在其响应中提供内容长度(Content-
Length)首部。而对于分块数据,由于响应的总长度未知,因此就无法估计
进度了。
另外,XHR 请求默认没有超时限制,这意味着一个请求的“进度”可以无限
长。作为最佳实践,一定要为应用设置合理的超时时间,并适当处理错误。
15.6 通过XHR实现流式数据传输
在某些场景下,应用可能需要或者应该递增地流式处理数据。比如,等到客户端数
据可用时上传,或者一边从服务器下载一边处理数据。可惜的是,尽管这种场景很
重要,但时至今日仍然没有一种简单有效和跨浏览器的 API 来实现 XHR 流:
• 上传时,send 方法只接受完整的载荷;
• response、responseText 和 responseXML 属性也不是为流设计的。
在 XHR 规范中,流式数据处理从未成为官方正式考虑的使用场景。于是,除了手
工把要上传的数据切分,再利用多个 XHR 请求迭代上传之外,没有其他 API 可以
实现客户端与服务器间的流式数据传输。类似地,虽然 XHR2 规范提供了读取服务
器部分响应的能力,但实现的效率却很低,而且有诸多限制。这一点确实令人沮丧。
234 | 第 15 章