loadScript.js

import { objectKeys } from './utils/native';
/**
 * 加载 js 文件。
 *
 * <em style="font-weight: bold;">注意:该方法仅适用于浏览器端。</em>
 *
 * @alias module:Browser.loadScript
 * @since 4.19.0
 * @param {string} src  js 地址。
 * @param {Object} [options] script 标签属性。比如 `defer` `onload` `onerror` `id` 等,下面列举部分带有默认值或额外扩展的配置。
 * @param {boolean} [options.destroyOnError=true] 如果加载失败或错误,自动删除 dom 中的 script 标签。默认`true`
 * @param {Object} [options.attrs] 自定义 script 属性,通过 script.setAttribute 设置。
 * @param {boolean} [options.async=true] 异步加载。默认`true`
 * @param {string} [options.type='text/javascript'] 类型。默认`text/javascript`
 * @return {Promise<HTMLScriptElement>} 异步返回 script 元素。
 * @example
 *
 * loadScript('some.js').then(script=>{
 *   // do something
 * })
 *
 * loadScript('some.js', { id: 'xxx', async: false, attrs: { foo: 'bar' } }).then(script=>{
 *   // do something
 * })
 *
 */
function loadScript(src, options) {
    return new Promise((resolve, reject) => {
        const container = document.head || document.getElementsByTagName('head')[0] || document.body;
        const script = document.createElement('script');
        const { attrs, destroyOnError = true, ...restOptions } = options || {};
        const props = {
            async: true,
            type: 'text/javascript',
            ...restOptions,
            src
        };
        for (const key in props) {
            if (key === 'onload' || key === 'onerror') {
                continue;
            }
            // @ts-ignore
            script[key] = props[key];
        }
        if (typeof attrs === 'object') {
            objectKeys(attrs).forEach((key) => {
                script.setAttribute(key, attrs[key]);
            });
        }
        script.onload = function (ev) {
            this.onerror = this.onload = null;
            props.onload?.call(this, ev);
            resolve(script);
        };
        script.onerror = function (ev) {
            this.onerror = this.onload = null;
            props.onerror?.call(this, ev);
            if (destroyOnError) {
                container.removeChild(script);
            }
            reject(new URIError('Failed to load ' + this.src));
        };
        container.appendChild(script);
    });
}
export default loadScript;