react中动态添加script标签并执行
let pointAndLineDataReady = false;
export const POINT_LINE_LIST = [
'http://10.110.10.15:9000/frontend/gis-model-point.min.js',
'http://10.110.10.15:9000/frontend/gis-model-line.min.js',
]
export const loadScript = (url) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script')
script.onload = () => resolve()
script.onerror = () => reject(new Error(`Load script from ${url} failed`))
script.src = url
const head = document.head || document.getElementsByTagName('head')[0];
(document.body || head).appendChild(script)
})
}
const loadPointAndLineData = () => {
if (window.gis_model_point && window.gis_model_line) { // 此处为了避免已经加载过script的重复下载
pointAndLineDataReady = true
return new Promise((resolve, reject) => { resolve() })
} else {
return POINT_LINE_LIST.reduce((res, el) => res.then(() => loadScript(el)), Promise.resolve()).then(() => {
console.log('loadPointAndLineData success')
pointAndLineDataReady = true
}).catch((error) => {
console.error('前置 js 资源加载失败:', error.name, error.message)
return Promise.reject(error)
})
}
}
useEffect(() => {
loadPointAndLineData().then(() => {
// dosomething...
})
}, [])
问题:
以上方式 每个script 是顺序加载,此处,我所需要的script没有执行顺序要求,所以又尝试使用Promise.all()来处理script异步加载,代码如下。
const loadPointAndLineData = () => {
if (window.gis_model_point && window.gis_model_line) {
pointAndLineDataReady = true
return new Promise((resolve, reject) => { resolve() })
} else {
const fetchUrls = []
POINT_LINE_LIST.forEach((el) => { fetchUrls.push(loadScript(el)) });
return Promise.all(fetchUrls).then(() => {
console.log('loadPointAndLineData success')
pointAndLineDataReady = true
}).catch((error) => {
console.error('前置 js 资源加载失败:', error.name, error.message)
return Promise.reject(error)
})
}
}
但是发现,网络情况一般的情况下,两者加载完成时间相差无几,待优化。
如果加载的url个数较多的情况下(此处使用的js为静态数据,受渲染影响较小),异步会快一丢丢。