【前端基础】script引入资源脚本加载失败解决方案(重新加载获取备用资源)

问题描述

现在假设有一个script资源加载失败,代码如下

html 复制代码
<!DOCTYPE html>
<html>
<head>
	<title>script 资源加载失败</title>
</head>
<body>
	<script src="http:hdh.sdas.asdas/1.js"></script>
</body>
</html>

我们希望在加载失败的时候进行一系列的解决操作,那么就需要有两步操作:

  1. 捕获加载失败事件
  2. 对加载失败操作进行处理(重新获取重试)

捕获加载失败事件

注意:

这里既然是捕获 script 资源加载错误,就要在 script 资源加载之前注册监听事件。因此把这段代码放在所有 script 标签之前

全局监听错误事件

true: 是一个可选的参数,表示在捕获阶段触发事件处理程序。在事件传播过程中,捕获阶段是指从最外层的元素向目标元素的阶段。这里设置为true表示在捕获阶段触发处理程序,如果设置为false或省略,则在冒泡阶段触发处理程序(从目标元素向最外层的元素)。

html 复制代码
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
	<title>script 资源加载失败</title>
	<script type="text/javascript">
		<!-- 这里需要添加 true 属性 -->
		window.addEventListener('error',(e)=>{
			console.log('有错误')
		},true)
	</script>
</head>
<body>
	<script src="http:hdh.sdas.asdas/1.js"></script>
</body>
</html>

捕获资源加载失败类型错误

首先我们打印一下监听事件的 e 元素,会发现 script 加载失败事件的属性和别的错误属性有两个特征,只要把握住这两个特征就可以进行判断处理:

  1. 特点1:是个 Event 对象
  2. 特点2:target 属性为 script
html 复制代码
<!DOCTYPE html>
<html>
<head>
	<title>script 资源加载失败</title>
	<script type="text/javascript">
		<!-- 这里需要添加 true 属性 -->
		window.addEventListener('error',(e)=>{
			const tag = e.target
			// 添加判断事件类型
			if(tag.tagName === 'SCRIPT' && !(e instanceof ErrorEvent)){
				console.log('有错误')
			}
		},true)
	</script>
</head>
<body>
	<script src="http:hdh.sdas.asdas/1.js"></script>
</body>
</html>

完整案例代码

html 复制代码
<!DOCTYPE html>
<html>
<head>
	<title>script 资源加载失败</title>
	<script type="text/javascript">

		// 这里是模拟的一些备用域名
		const domains = [
			'test.1.com',
			'test.2.com',
			'test.3.com'
		]
		// 最大的重试次数
		const maxRetry = 5
		// 资源加载信息
		const retryInfo = {}

		window.addEventListener('error',(e)=>{

			console.log('e',e)
			const tag = e.target

			// 只对 script 加载失败错误进行处理
			if(tag.tagName === 'SCRIPT' && !(e instanceof ErrorEvent)){
				const url = new URL(tag.src)
				console.log('url',url)

				// 如果该文件没有加载失败信息,则初始化
				if(!retryInfo[url.pathname]){
					retryInfo[url.pathname] = {
						times:0,
						nextIndex:0
					}
				}

				const info = retryInfo[url.pathname]
				console.log('info',retryInfo)

				// 加载失败次数小于最大重试次数
				if(info.times < maxRetry){
					url.host = domains[info.nextIndex]

					// 阻塞页面后续的加载
					document.write(`<script src="${url.toString()}">\<\/script>`)

					// 以下这种方式就不会按顺序加载 script 内容
					// const script = document.createElement('script')
					// script.src = url.toString()
					// document.body.insertBefore(script,tag)

					// 下标循环
					info.nextIndex = (info.nextIndex + 1) % domains.length
					info.times++
				}
			}
		},true)
	</script>
</head>
<body>
	<!-- 模拟一个加载失败的资源 -->
	<script src="http:hdh.sdas.asdas/1.js"></script>
</body>
</html>
相关推荐
小碗羊肉几秒前
【从零开始学Java | 第二十二篇】List集合
java·开发语言
m0_716765232 分钟前
C++提高编程--STL常用容器(set/multiset、map/multimap容器)详解
java·开发语言·c++·经验分享·学习·青少年编程·visual studio
天若有情6732 分钟前
前端HTML精讲01:别再乱 div 一把抓,吃透语义化标签才是进阶第一步
前端·html
Highcharts.js3 分钟前
React 开发者的图表库生态:Highcharts React
前端·react.js·前端框架
阿部多瑞 ABU3 分钟前
文明文化悖论
前端·人工智能·ai写作
钛态23 分钟前
Flutter 三方库 react 泛前端核心范式框架鸿蒙原生层生态级双向超能适配:跨时空重塑响应式单向数据流拓扑与高度精密生命周期树引擎解耦视图渲染控制中枢(适配鸿蒙 HarmonyOS ohos)
前端·flutter·react.js
全栈前端老曹24 分钟前
【前端地图】地图开发基础概念——地图服务类型(矢量图、卫星图、地形图)、WGS84 / GCJ-02 / BD09 坐标系、地图 SDK 简介
前端·javascript·地图·wgs84·gcj-02·bd09·地图sdk
只与明月听24 分钟前
RAG深入学习之向量数据库
前端·人工智能·python
froginwe1129 分钟前
Bootstrap4 折叠组件使用指南
开发语言
sunwenjian88630 分钟前
SpringBean的生命周期
java·开发语言