• Home
  • Explore
  • Detail

脚本加载失败后如何重试?

3 views

## 前言

让我们看一个例子,假设一个 html 文件中引入了如下 js 文件。

![image.png](https://chgrr6wzjqcjltyx.public.blob.vercel-storage.com/image\_3b297f90e0a7146caf0eb5b22ab7c8ab-uEdEkXKagT0dJz1o9PjbYWFWeWqrev.png "image.png")

假如某些情况下导致某个 js 无法加载出来,我们要尽量避免影响用户。

> 因为目前大多都是单页面应用,某些js未加载肯定会对功能上有影响。

那如何解决?

> 多数情况需要重试,或者换个域名再重试。

> 因此解决办法主要围绕重试,得出两个关键点:

> 1. 何时重试?

> 2. 如何重试?

## 何时重试?

当然是js加载失败的时候重试。

我们可以这样写:

![image.png](https://chgrr6wzjqcjltyx.public.blob.vercel-storage.com/image\_1fd2e83ba487842816c60c9fd14a1af4-yXwgKKh0wdI37nCiPFGDJJZSI9Y6Ai.png "image.png")

> 请注意这里两个细节:

> 1. script 位置

> 2. listener 中第三个参数为 true,表示捕获事件而非冒泡事件。

## 如何重试?

```js

<script>

const domains = ["xxx1.com", "xxx2.com", "xxx3,com"];

const retry = {};

window.addEventListener(

"error",

(e) => {

if (e instanceof ErrorEvent || e.target.tagName !== "SCRIPT") {

return;

}

const url = new URL(e.target.src);

const pathname = url.pathname;

if (!(pathname in retry)) {

retry[pathname] = 0;

}

const index = retry[pathname];

if (index >= domains.length) {

return;

}

const newDomain = domains[index];

url.host = newDomain;

document.write(`\<script src="${url.toString()}"><\/script>`);

// const script = document.createElement("script");

// script.src = url.toString();

// e.target.parentElement.insertBefore(script, e.target);

retry[pathname]++;

e.target.remove();

},

true

);

</script>

```

[](https://codesandbox.io/p/sandbox/28f79h)

最终得到的效果:

![image.png](https://chgrr6wzjqcjltyx.public.blob.vercel-storage.com/image\_8462bccedd7c65b85ef8863ee436f824-SMsyLUetQ9C41JKHapDIW4fPrx9XpJ.png "image.png")