initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
133
platform/web/js/engine/preloader.js
Normal file
133
platform/web/js/engine/preloader.js
Normal file
@@ -0,0 +1,133 @@
|
||||
const Preloader = /** @constructor */ function () { // eslint-disable-line no-unused-vars
|
||||
function getTrackedResponse(response, load_status) {
|
||||
function onloadprogress(reader, controller) {
|
||||
return reader.read().then(function (result) {
|
||||
if (load_status.done) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (result.value) {
|
||||
controller.enqueue(result.value);
|
||||
load_status.loaded += result.value.length;
|
||||
}
|
||||
if (!result.done) {
|
||||
return onloadprogress(reader, controller);
|
||||
}
|
||||
load_status.done = true;
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
const reader = response.body.getReader();
|
||||
return new Response(new ReadableStream({
|
||||
start: function (controller) {
|
||||
onloadprogress(reader, controller).then(function () {
|
||||
controller.close();
|
||||
});
|
||||
},
|
||||
}), { headers: response.headers });
|
||||
}
|
||||
|
||||
function loadFetch(file, tracker, fileSize, raw) {
|
||||
tracker[file] = {
|
||||
total: fileSize || 0,
|
||||
loaded: 0,
|
||||
done: false,
|
||||
};
|
||||
return fetch(file).then(function (response) {
|
||||
if (!response.ok) {
|
||||
return Promise.reject(new Error(`Failed loading file '${file}'`));
|
||||
}
|
||||
const tr = getTrackedResponse(response, tracker[file]);
|
||||
if (raw) {
|
||||
return Promise.resolve(tr);
|
||||
}
|
||||
return tr.arrayBuffer();
|
||||
});
|
||||
}
|
||||
|
||||
function retry(func, attempts = 1) {
|
||||
function onerror(err) {
|
||||
if (attempts <= 1) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
retry(func, attempts - 1).then(resolve).catch(reject);
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
return func().catch(onerror);
|
||||
}
|
||||
|
||||
const DOWNLOAD_ATTEMPTS_MAX = 4;
|
||||
const loadingFiles = {};
|
||||
const lastProgress = { loaded: 0, total: 0 };
|
||||
let progressFunc = null;
|
||||
|
||||
const animateProgress = function () {
|
||||
let loaded = 0;
|
||||
let total = 0;
|
||||
let totalIsValid = true;
|
||||
let progressIsFinal = true;
|
||||
|
||||
Object.keys(loadingFiles).forEach(function (file) {
|
||||
const stat = loadingFiles[file];
|
||||
if (!stat.done) {
|
||||
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, fileSize, raw = false) {
|
||||
return retry(loadFetch.bind(null, file, loadingFiles, fileSize, raw), DOWNLOAD_ATTEMPTS_MAX);
|
||||
};
|
||||
|
||||
this.preloadedFiles = [];
|
||||
this.preload = function (pathOrBuffer, destPath, fileSize) {
|
||||
let buffer = null;
|
||||
if (typeof pathOrBuffer === 'string') {
|
||||
const me = this;
|
||||
return this.loadPromise(pathOrBuffer, fileSize).then(function (buf) {
|
||||
me.preloadedFiles.push({
|
||||
path: destPath || pathOrBuffer,
|
||||
buffer: buf,
|
||||
});
|
||||
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();
|
||||
}
|
||||
return Promise.reject(new Error('Invalid object for preloading'));
|
||||
};
|
||||
};
|
Reference in New Issue
Block a user