下载微小文件时如何在Javascript中显示进度条? [英] How to display a progress bar in Javascript while downloading a tiny file?

查看:58
本文介绍了下载微小文件时如何在Javascript中显示进度条?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了以下函数来处理Ajax请求以获取数据;

I wrote the following function to process an Ajax request to fetch data;

var xhr = createCORSRequest('GET', url);
if (!xhr) {
    alert('CORS not supported');
    return;
}
xhr.onload = function() {
    var txt1 = xhr.responsetxt1;
    var heading = getheading(txt1);

    if (heading == 'PASS') {
        var file = "My_URL" + ".js";
        downloadFile(file);
        //My code to display a progress bar here?
    } else {
        //Logic to handle failure to load
    }
};

这是我的 downloadFile 函数,用于下载文件.但是,我不知道该怎么做:

Here is my downloadFile function to download the file. But, I don't understand how to:

  • 检查下载是否完成.
  • 显示进度条以显示进度.

如果您可以添加有关其工作方式的说明,那将是很好的.谢谢.

If you can add a description of how it works, that'd be great. Thanks.

function downloadFile(fileName) {
    (function(d) {
        var ref = d.getElementsByTagName('script')[0];
        var js = d.createElement('script');
        js.src = fileName;
        ref.parentNode.insertBefore(js, ref);
        // My code to display a progress bar here?
    }(document));
}

推荐答案

AFAIK ,脚本元素没有进度事件.最好的选择是使用XHR获取脚本的正文,然后依靠浏览器缓存进行第二次提取.问题在于您的脚本随后需要由浏览器解析,并且似乎没有事件发生.

AFAIK, script elements don't have progress events. Your best bet is to use an XHR to get the script's body, then count on the browser cache for a second fetch. The problem is that your script then needs to be parsed by the browser, and there doesn't seem to be events for that.

我的解决方案是纯JS,因此您可以使其适应所使用的任何框架.假设实际下载量约为总时间的70%,并为浏览器解析分配20%的时间.我使用了很棒的 three.js 3D 库的最小版本作为很大的源文件.

My solution is pure JS, so you can adapt it to whatever framework you're using. It assumes that actual download will be about 70% of the total time, and allocates 20 % to the browser parsing. I use a non-minified versionof the awesome three.js 3D library as a biggish source file.

因为它在另一个沙箱中,所以进度调用的计算是不准确的,但是如果您提供自己的脚本,那应该没问题.

because it is in another sandbox, progress callculation is inaccurate, but if you serve your own script that shouldn't be a problem.

请记住,这是一个精简的实现.例如,我使用一个简单的HR作为进度条.

keep in mind that this is a fairly stripped down implementation. I used a simple HR as a progress bar, for example.

//this is a rough size estimate for my example file
let TOTAL_ESTIMATE = 1016 * 1024;
// I use a hr as a 
let bar = document.getElementById("progressbar");
let button = document.getElementById("dlbtn");

var js; // to hold the created dom element
var fileName; // to hold my cacheBusted script adress

/* this function will be called several times during (the first) download, with info about how much data is loaded */

function onProgress(e) {
  var percentComplete = e.loaded / TOTAL_ESTIMATE;
  if (e.lengthComputable) {
    percentComplete = e.loaded / e.total;
  }
  p = Math.round(percentComplete * 100);
  console.log("progress", p + "%,", e.loaded, "bytes loaded")
  bar.style = "width: " + (5 + .6 * p) + "%"; // I just assume dl will be around 60-70% of total time

}

/* this function is called when info comes. at the end of the initial download, the readystate will be 4 so we then set the file's src attribute, triggering a re-download but taking advantage of the browser's cache. It's not ideal, and simply `eval` ing the data would probably yield better results. I just assumed you wanted a <script> tag on your page, and for it to be evaluated. */ 
function onReadyState(e) {
  let r = e.target;
  //this is lifted almost verbatim from http://vanilla-js.com/ ;)
  if (r.readyState != 4 || r.status != 200)
    return;
  let l = r.responseText.length;
  console.log("Success !", l, "bytes total (" + Math.round(l / 1024) + " KB )");
  bar.style = "width: 70%";
  //just add / to next line to toggle ending methods
  /* you could speed up the proces by simply eval()ing the returned js. like so (please be aware of security concerns) :
  eval.bind(window)(r.responseText);
  onScriptLoaded();
  /*/

  js.src = fileName;
  bar.style = "width: 80%";
  var ref = document.getElementsByTagName('script')[0];
  ref.parentNode.insertBefore(js, ref);
  //*/
  
};

//this is called when the script has been evaluated :
function onScriptLoaded() {
  bar.style = "width: 100%; background-color: lightgreen;";
  button.disabled = false;
  console.log("script has been evaluated ?", THREE ? "yes" : "no"); // the demo file exposes window.THREE
}

function downloadFile(file) {
  button.disabled = true;
  (function(d) {
    // this helps to test this script multiple times. don't keep it
    fileName = file + "?bustCache=" + new Date().getTime();


    console.log("inserting new script");
    js = d.createElement('script');
    js.type = "text/javascript";
    js.defer = "defer";
    js.async = "async";
    var r = new XMLHttpRequest();
    bar.style = "width: 5%"; //always react ASAP
    r.addEventListener("progress", onProgress);
    r.open("GET", fileName, true);
    r.onreadystatechange = onReadyState;
    js.onload = onScriptLoaded;
    r.send();
    // My code to display a progress bar here?
  }(document));
}

#progressbar {
  height: 6px;
  border-radius: 3px;
  width: 0%;
  border-color: green;
  background-color: green;
}

<button onclick="downloadFile('https://rawgit.com/mrdoob/three.js/dev/build/three.js', this)" id="dlbtn">Download</button>
<script id="dummy" type="text/javascript">
  console.log("dummy script ready")
</script>
<hr id="progressbar" align="left" />

这篇关于下载微小文件时如何在Javascript中显示进度条?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆