getScript在前端中请求js文件和jsonp
侧边栏壁纸
  • 累计撰写 1,061 篇文章
  • 累计收到 0 条评论

getScript在前端中请求js文件和jsonp

加速器之家
2024-10-20 / 0 评论 / 3 阅读 / 正在检测是否收录...

getScript在前端中使用的非常广泛,那么这里也分享下自己使用的ts版本的getScript:

/**
* 加载js文件
* @param {string} url 要加载的js文件链接
* @param {function} callback 回调函数
* @returns {Promise} 返回一个Promise对象,若加载失败或者超时,则reject
*/
const getScript = (url: string, callback: ()=>{}): Promise<null> => { const head = document.getElementsByTagName('head')[0]; const script = document.createElement('script'); const timeout: number = 5000; // 过期时间 let timer: number; script.setAttribute('type', 'text/javascript'); script.setAttribute('charset', 'UTF-8'); script.setAttribute('src', url); if (sid) { script.setAttribute('id', sid); } const cleanup = () => { if (script.parentNode) { script.parentNode.removeChild(script); } if (timer) { clearTimeout(timer); } }; head.appendChild(script); return new Promise((resolve, reject) => { // 执行回调 const callbackFn = () => { if (timer) { clearTimeout(timer); } callback(); resolve(); }; script.onload = () => { callbackFn(); }; if (timeout) { timer = setTimeout(() => { cleanup(); reject(new Error(`get ${url} timeout`)); }, timeout); } }); };

正常请求一个js文件,然后设置了一个5000ms的过期时间,若请求资源不成功,则进入到reject中。同时,getScript支持使用callback和Promise两种方式执行结果的回调,不过callback的方式无法获取到超时的情况:

getScript('http://mat1.gtimg.com/libs/jquery2/2.2.0/jquery.min.js').then((jQuery: any)=>{
    console.log(jQuery.fn.jquery);
}).catch(e=>console.error('请求超时'));

这种方式,其实稍微改造一下,也是可以直接用来跨域,请求支持jsonp接口的。在url的后面添加上callback的请求参数,然后在回调里执行这个callback。
例如:

const getScript = (url: string, data: {}): Promise => {
    const head = document.getElementsByTagName('head')[0];
    const script = document.createElement('script');
    const timeout: number = 5000; // 过期时间
    let timer: number;
    let fecthCallBack: string = 'cb' + Date.now() + '_' + ('' + Math.random()).substr(-8);

    const cleanup = () => {
        if (script.parentNode) {
            script.parentNode.removeChild(script);
        }
        window[fecthCallBack] = () => {};
        delete window[fecthCallBack];
        if (timer) {
            clearTimeout(timer);
        }
    };
    head.appendChild(script);

    // 将Object类型的数据转换为URL链接需要的参数
    let paramObj = (params: any) => {
        let str = '',
            key,
            item;
        for (key in params) {
            if (typeof params[key] === 'object') {
                item = JSON.stringify(params[key]);
            } else {
                item = params[key];
            }
            str += `&${key}=${encodeURIComponent(item)}`;
        }
        return str.substring(1);
    };

    url += (~url.indexOf('?') ? '&' : '?') + paramObj(data) + '&callback=' + fecthCallBack;

    script.setAttribute('type', 'text/javascript');
    script.setAttribute('charset', 'UTF-8');
    script.setAttribute('src', url);

    return new Promise((resolve, reject) => {
        window[fecthCallBack] = (data: any) => {
            cleanup();
            resolve(data);
        };

        if (timeout) {
            timer = setTimeout(() => {
                cleanup();
                reject(new Error('Timeout'));
            }, timeout);
        }
    });
};

0

评论

博主关闭了当前页面的评论