t-comm
Version:
专业、稳定、纯粹的工具库
164 lines (162 loc) • 5.55 kB
JavaScript
var addScript = function addScript(script) {
var _a;
// Get the first script element, we're just going to use it
// as a reference for where to insert ours. Do NOT try to do
// this just once at the top and then re-use the same script
// as a reference later. Some weird loaders *remove* script
// elements after the browser has executed their contents,
// so the same reference might not have a parentNode later.
var firstScript = document.getElementsByTagName('script')[0];
// Append the script to the DOM, triggering execution.
(_a = firstScript === null || firstScript === void 0 ? void 0 : firstScript.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(script, firstScript);
};
/**
* 以 Callback 的方式加载 js 文件
* @param {String} src js文件路径
* @param {Function|Object} callback 加载回调
* @param {String} charset 指定js的字符集
* @param {Object} context Callback context
*/
var loader = function loader(src, callback, charset, context) {
if (charset === void 0) {
charset = 'utf-8';
}
if (context === void 0) {
context = null;
}
var setup;
if (callback && typeof callback !== 'function') {
context = callback.context || context;
setup = callback.setup;
callback = callback.callback;
}
var done = false;
var err;
var privateCleanup; // _must_ be set below.
/**
* Final handler for error or completion.
*
* **Note**: Will only be called _once_.
*
* @returns {void}
*/
var privateFinish = function privateFinish() {
// Only call once.
if (done) {
return;
}
done = true;
// Internal cleanup.
privateCleanup === null || privateCleanup === void 0 ? void 0 : privateCleanup();
// Callback.
if (callback) {
callback.call(context, err);
}
};
/**
* Error handler
*
* @returns {void}
*/
var privateError = function privateError() {
err = new Error(src || 'EMPTY');
privateFinish();
};
var curScript = document.querySelector("script[src=\"".concat(src, "\"]"));
if (curScript) {
var tc_1 = setInterval(function () {
if (curScript.isready) {
// 判断js加载完成
privateFinish();
clearInterval(tc_1);
}
}, 20);
} else {
var script_1 = document.createElement('script');
script_1.isready = false;
if (script_1.readyState && !('async' in script_1)) {
var isReady_1 = {
loaded: true,
complete: true
};
var inserted_1 = false;
// Clear out listeners, state.
privateCleanup = function privateCleanup() {
script_1.onreadystatechange = null;
script_1.onerror = null;
};
// Attach the handler before setting src, otherwise we might
// miss events (consider that IE could fire them synchronously
// upon setting src, for example).
script_1.onreadystatechange = function () {
var firstState = script_1.readyState;
// Protect against any errors from state change randomness.
if (err) {
return;
}
if (!inserted_1 && isReady_1[firstState]) {
inserted_1 = true;
// Append to DOM.
addScript(script_1);
}
if (firstState === 'loaded') {
// The act of accessing the property should change the script's
// `readyState`.
//
// And, oh yeah, this hack is so hacky-ish we need the following
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
script_1.children;
if (script_1.readyState === 'loading') {
// State transitions indicate we've hit the load error.
//
// **Note**: We are not intending to _return_ a value, just have
// a shorter short-circuit code path here.
return privateError();
}
}
// It's possible for readyState to be "complete" immediately
// after we insert (and execute) the script in the branch
// above. So check readyState again here and react without
// waiting for another onreadystatechange.
if (script_1.readyState === 'complete') {
script_1.isready = true;
privateFinish();
}
};
// Onerror handler _may_ work here.
script_1.onerror = privateError;
// call the setup callback to mutate the script tag
if (setup) {
setup.call(context, script_1);
}
// This triggers a request for the script, but its contents won't
// be executed until we append it to the DOM.
script_1.src = src;
// In some cases, the readyState is already "loaded" immediately
// after setting src. It's a lie! Don't append to the DOM until
// the onreadystatechange event says so.
} else {
// This section is for modern browsers, including IE10+.
// Clear out listeners.
privateCleanup = function privateCleanup() {
script_1.onload = null;
script_1.onerror = null;
};
script_1.onerror = privateError;
script_1.onload = function () {
script_1.isready = true;
privateFinish();
};
script_1.async = true;
script_1.charset = charset || 'utf-8';
// call the setup callback to mutate the script tag
if (setup) {
setup.call(context, script_1);
}
script_1.src = src;
// Append to DOM.
addScript(script_1);
}
}
};
export { loader };