summaryrefslogtreecommitdiff
path: root/platform/javascript/js/engine/preloader.js
diff options
context:
space:
mode:
Diffstat (limited to 'platform/javascript/js/engine/preloader.js')
-rw-r--r--platform/javascript/js/engine/preloader.js129
1 files changed, 129 insertions, 0 deletions
diff --git a/platform/javascript/js/engine/preloader.js b/platform/javascript/js/engine/preloader.js
new file mode 100644
index 0000000000..8641646e6e
--- /dev/null
+++ b/platform/javascript/js/engine/preloader.js
@@ -0,0 +1,129 @@
+var Preloader = /** @constructor */ function() { // eslint-disable-line no-unused-vars
+
+ const loadXHR = function(resolve, reject, file, tracker, attempts) {
+ const xhr = new XMLHttpRequest();
+ tracker[file] = {
+ total: 0,
+ loaded: 0,
+ final: false,
+ };
+ xhr.onerror = function() {
+ if (attempts <= 1) {
+ reject(new Error("Failed loading file '" + file + "'"));
+ } else {
+ setTimeout(function () {
+ loadXHR(resolve, reject, file, tracker, attempts - 1);
+ }, 1000);
+ }
+ };
+ xhr.onabort = function() {
+ tracker[file].final = true;
+ reject(new Error("Loading file '" + file + "' was aborted."));
+ };
+ xhr.onloadstart = function(ev) {
+ tracker[file].total = ev.total;
+ tracker[file].loaded = ev.loaded;
+ };
+ xhr.onprogress = function(ev) {
+ tracker[file].loaded = ev.loaded;
+ tracker[file].total = ev.total;
+ };
+ xhr.onload = function() {
+ if (xhr.status >= 400) {
+ if (xhr.status < 500 || attempts <= 1) {
+ reject(new Error("Failed loading file '" + file + "': " + xhr.statusText));
+ xhr.abort();
+ } else {
+ setTimeout(function () {
+ loadXHR(resolve, reject, file, tracker, attempts - 1);
+ }, 1000);
+ }
+ } else {
+ tracker[file].final = true;
+ resolve(xhr);
+ }
+ };
+ // Make request.
+ xhr.open('GET', file);
+ if (!file.endsWith('.js')) {
+ xhr.responseType = 'arraybuffer';
+ }
+ xhr.send();
+ };
+
+ const DOWNLOAD_ATTEMPTS_MAX = 4;
+ const loadingFiles = {};
+ const lastProgress = { loaded: 0, total: 0 };
+ let progressFunc = null;
+
+ const animateProgress = function() {
+
+ var loaded = 0;
+ var total = 0;
+ var totalIsValid = true;
+ var progressIsFinal = true;
+
+ Object.keys(loadingFiles).forEach(function(file) {
+ const stat = loadingFiles[file];
+ if (!stat.final) {
+ progressIsFinal = false;
+ }
+ if (!totalIsValid || stat.total === 0) {
+ totalIsValid = false;
+ total = 0;
+ } else {
+ total += stat.total;
+ }
+ loaded += stat.loaded;
+ });
+ if (loaded !== lastProgress.loaded || total !== lastProgress.total) {
+ lastProgress.loaded = loaded;
+ lastProgress.total = total;
+ if (typeof progressFunc === 'function')
+ progressFunc(loaded, total);
+ }
+ if (!progressIsFinal)
+ requestAnimationFrame(animateProgress);
+ }
+
+ this.animateProgress = animateProgress;
+
+ this.setProgressFunc = function(callback) {
+ progressFunc = callback;
+ }
+
+
+ this.loadPromise = function(file) {
+ return new Promise(function(resolve, reject) {
+ loadXHR(resolve, reject, file, loadingFiles, DOWNLOAD_ATTEMPTS_MAX);
+ });
+ }
+
+ this.preloadedFiles = [];
+ this.preload = function(pathOrBuffer, destPath) {
+ let buffer = null;
+ if (typeof pathOrBuffer === 'string') {
+ var me = this;
+ return this.loadPromise(pathOrBuffer).then(function(xhr) {
+ me.preloadedFiles.push({
+ path: destPath || pathOrBuffer,
+ buffer: xhr.response
+ });
+ return Promise.resolve();
+ });
+ } else if (pathOrBuffer instanceof ArrayBuffer) {
+ buffer = new Uint8Array(pathOrBuffer);
+ } else if (ArrayBuffer.isView(pathOrBuffer)) {
+ buffer = new Uint8Array(pathOrBuffer.buffer);
+ }
+ if (buffer) {
+ this.preloadedFiles.push({
+ path: destPath,
+ buffer: pathOrBuffer
+ });
+ return Promise.resolve();
+ } else {
+ return Promise.reject(new Error("Invalid object for preloading"));
+ }
+ };
+};