繁体   English   中英

JS ProgressEvent仅在完成时触发

[英]JS ProgressEvent is only fired when finished

我在上传进度条正常工作时遇到了一些问题。

根据XMLHttpRequest Level 2规范,我为loadstart附加了事件监听器,并且进展如下:

var xhr = $.ajaxSettings.xhr();
xhr.upload.addEventListener('loadstart', function(e) {progressCallback(0);});
xhr.upload.addEventListener('progress', function (e) {
    progressCallback(e.loaded / e.total);
});    

$.ajax({
    url: url,
    type: 'POST',
    processData: false,
    contentType: false,
    data: formData,
    xhr: function () {
        return xhr;
    }
}).done(function (data) {
    // Finish stuff
})

文件已正确上传,但只有在请求以100%完成后才会调用进度监听器(e.total == e.loaded)

上面的代码有什么问题,或者是否有必要以任何特殊方式配置服务器?

当无法确定文件的总大小时, e.loadede.total为零。 你可以在progress函数中检查这个:

if (evt.lengthComputable) {
    progressCallback(e.loaded / e.total);
}

服务器还必须发送规范中定义的Content-Length

如果通过Content-Length标头知道HTTP实体主体的长度,则将lengthComputable属性初始化为true,并将total属性初始化为length。

另请注意,进度条不适用于file: protocol。

我真的可以推荐非常广泛的Mozilla文档 - 使用XMLHTTPRequest Mozilla文档

我自己遇到了类似的问题,我在XMLHttpRequest上的progress事件的事件处理函数只执行了一次 - 当上传完成时。

问题的原因最终变得简单 - 在谷歌浏览器(可能还有其他浏览器,我没有测试),如果上传已经运行了一两秒, progress事件将只会连续触发。 换句话说,如果您的上传速度很快,那么您可能只会获得一次100%的progress事件。

这是一个代码示例,其progress事件仅在100%完成时触发一次( https://jsfiddle.net/qahs40r6/ ):

$.ajax({
  xhr: function()
  {
    var xhr = new window.XMLHttpRequest();
    //Upload progress
    xhr.upload.addEventListener("progress", function(evt){
      if (evt.lengthComputable) {
        var percentComplete = evt.loaded / evt.total;
        console.log("Upload ", Math.round(percentComplete*100) + "% complete.");
      }
    }, false);
    return xhr;
  },
  type: 'POST',
  url: "/echo/json/",
  data: {json: JSON.stringify(new Array(20000))}
});

控制台输出:

Upload  100% complete.

但是如果你在数组的大小上增加一个额外的零(将有效负载大小增加10倍 - https://jsfiddle.net/qahs40r6/1/ ):

$.ajax({
  xhr: function()
  {
    var xhr = new window.XMLHttpRequest();
    //Upload progress
    xhr.upload.addEventListener("progress", function(evt){
      if (evt.lengthComputable) {
        var percentComplete = evt.loaded / evt.total;
        console.log("Upload ", Math.round(percentComplete*100) + "% complete.");
      }
    }, false);
    return xhr;
  },
  type: 'POST',
  url: "/echo/json/",
  data: {json: JSON.stringify(new Array(200000))}
});

然后,您将获得progress事件的正常进展:

Upload  8% complete.
Upload  9% complete.
Upload  19% complete.
Upload  39% complete.
Upload  50% complete.
Upload  81% complete.
Upload  85% complete.
Upload  89% complete.
Upload  100% complete.

此行为取决于您的Internet连接速度,因此您的里程会有所不同。 例如,如果您采用第一个示例并使用Chrome开发者工具来减慢与模拟“慢速3G”的连接速度,那么您将看到一系列progress事件。

同样,如果您在本地开发并将数据上传到本地Web服务器,您可能永远不会看到progress事件,因为上传将立即完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM