惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
Google DeepMind News
Google DeepMind News
MyScale Blog
MyScale Blog
A
About on SuperTechFans
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
Recent Announcements
Recent Announcements
D
DataBreaches.Net
B
Blog
博客园 - 【当耐特】
爱范儿
爱范儿
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
WordPress大学
WordPress大学
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
I
InfoQ
Engineering at Meta
Engineering at Meta
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Last Week in AI
Last Week in AI
Microsoft Azure Blog
Microsoft Azure Blog
雷峰网
雷峰网
量子位
G
Google Developers Blog

蚊子的前端博客

微说 | 有的人觉得只要不考XX,一定能考好!-蚊子的前端博客 微说 | 春天来了-蚊子的前端博客 明天和意外不知道哪个先来-蚊子的前端博客 微说 | 既然错过了路口,就及时止损,重新规划路线上路-蚊子的前端博客 微说 | 2025年的出生人口数是792万-蚊子的前端博客 微说 | 工作年终总结,让写对接的接口的数量?-蚊子的前端博客 微说 | 温家宝:没有政治体制改革的成功 经济体制改革不可能进行到底-蚊子的前端博客 微说 | 违法犯罪了该不该被禁言?-蚊子的前端博客 微说 | 不明白为什么在推荐去俄罗斯旅游-蚊子的前端博客 微说 | 易中天论骗子-蚊子的前端博客 微说 | 一场大风吹散了秋天-蚊子的前端博客 微说 | 既要、又要、还要、更要!-蚊子的前端博客 又是一年的国庆雨季-蚊子的前端博客 微说 | 预估下2025年的出生人口数据-蚊子的前端博客 微说 | 可惜了我那些小时候的书本-蚊子的前端博客 微说 | 牛马有的是,驴不够了!-蚊子的前端博客 微说 | 能否有一条非户口也能高考的路-蚊子的前端博客 微说 | 小聊中医-蚊子的前端博客 微说 | 将要制作的一款新产品-蚊子的前端博客 微说 | 做人要有信-蚊子的前端博客 微说 | 好一个正义联盟-蚊子的前端博客 微说 | 都是见过吃过的主儿-蚊子的前端博客 微说 | 追求8小时工作制有错吗?-蚊子的前端博客 微说 | 如果尖锐的批评完全消失-蚊子的前端博客 微说 | 很好!-蚊子的前端博客 微说 | 封禁用户可以,但要告知具体原因-蚊子的前端博客 微说 | 面朝大海,春暖花开-蚊子的前端博客 微说 | 程序员的悲哀是什么?-蚊子的前端博客 微说 | 2025年出生人口的预测-蚊子的前端博客 前端在 LiveKit 中如何获取所有的参与者-蚊子的前端博客
getScript在前端中请求js文件和jsonp-蚊子的前端博客
author · 2019-02-27 · via 蚊子的前端博客

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<any> => {
    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);
        }
    });
};