Dynamically load JavaScript and track download progress

High level: I use Emscripten to convert various legacy C / C ++ code bases to optimized JavaScript so that a modern browser-based database can easily use their functionality. So far, so good. However, Emscripten-transpiled JS can be a bit cumbersome even after compression for network delivery.

To improve the user interface, I want to load this giant piece of JS after loading the main page, and I want to track the progress of loading to display in the user interface of the page. I know two approaches to dynamic loading, and I am faced with the disadvantages of both:

  • The first approach is to create a script tag (embedded in an HTML page or dynamically generated JS). The event is onloadfired when the file is uploaded and ready to run. The problem with this approach is that I cannot find a way to track the progress of the download. The script object has an event onprogress, but it does nothing (tested in Chrome).
  • Use the XMLHTTPRequest (XHR) object to dynamically query a JS resource. This works well and fires the expected download progress events. However, starting JS eval()in the loaded data does not have the right effect (expected functions do not appear in the JS namespace).

Running eval()simpler lines with JS support has the expected result, so I'm wondering if there is any special trick to run eval()in compiled Emscripten code.

Instead, I implemented a hybrid solution combining approaches 1 and 2 above: XHR does the initial load and throws the data. The page then creates a script element to load the same JS file, which is now in the browser cache and loads instantly. But this is obviously a hack, and I cannot help but think that there should be a cleaner solution.

+4
source share
1 answer

Instead of discarding data, set the data to a script tag.

var xhr = new XMLHttpRequest;
var tag = document.createElement("script");
xhr.open("GET", "foo.js", true);
xhr.onload = function (e) {
  if (xhr.readyState === 4) {
    if (xhr.status === 200) {
      tag.text = xhr.response;
      document.head.appendChild(tag);
    } else {
      alert("error");
      console.error(xhr.response);
    }
  }
};
xhr.onprogress = function (e) {
  Module.setStatus('Loading JavaScript: ' + (100 * e.loaded / + e.total) + '%');
};
xhr.send();
+3
source

Source: https://habr.com/ru/post/1616970/


All Articles