手写实现从网络异步加载js脚本,并返回Promise实例,如果加载成功就执行resolve,失败或超时就执行reject。
/**
* 异步加载函数
* @param src 脚本 url 地址
* @param delay 加载的最大允许时间
*/
function asyncLoad(src, delay) {
return new Promise((resolve, reject) => {
// 创建一个 script 元素
const script = document.createElement('script');
// type 属性也可以不设置
script.type = 'text/javascript';
// 指定 src 的值
script.src = src;
// 将元素添加进 DOM 文档
document.body.appendChild(script);
const ERROR_STR = '加载失败';
// 设置超时函数
const timer = setTimeout(() => {
reject(ERROR_STR);
}, delay);
// 设置监听状态的回调函数
if (script.readyState) { // IE
script.onreadstatechange = function() {
// 取消计时函数
clearTimeout(timer);
if (['loaded', 'complete'].includes(script.readyState)) {
script.onreadstatechange = null;
resolve();
} else { // 加载失败的情况
reject(ERROR_STR);
}
}
} else { // Chrome、Edge、Safari、Firefox 等
script.onload = function() {
clearTimeout(timer);
resolve();
}
}
});
}
// 测试代码
const src = 'http://libs.baidu.com/jquery/2.0.0/jquery.min.js';
const start = Date.now();
asyncLoad(src, 5000).then(() => {
// 此时 jQuery 已经加载,可以使用 $ 来选择元素
$('#app')[0].textContent = `加载完毕,耗时:${Date.now() - start} ms`;
}).catch(err => {
const app = document.getElementById('app');
app.textContent = err;
});