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 章
   242   243   244   245   246   247   248   249   250   251   252