面试官:当网页资源加载失败时,你怎么处理?

在千差万别的网络状态中,访问页面难免会遇到前端资源加载失败的情况,占比或许不高,但一遇到,轻则页面样式错乱,重则白屏打不开,影响用户体验感受,紧急情况下甚至影响了用户的工作,属于非常严重的问题。

资源加载失败的影响

  1. 用户体验受损:资源加载失败最直接的影响就是用户体验。页面样式错乱、图片无法显示、视频无法播放,以及关键功能无法使用,都会给用户带来困扰和不满。特别是在移动设备或网络状况不佳的情况下,资源加载失败的概率更高,对用户体验的损害也更为严重。

  2. 页面功能受限:前端资源通常包括JavaScript脚本、CSS样式表、图片、字体等,这些资源对于页面的正常运行至关重要。如果某个关键资源加载失败,可能会导致页面功能受限或完全失效。例如,JavaScript脚本加载失败可能导致页面交互功能无法正常工作,CSS样式表加载失败可能导致页面布局混乱。

  3. 性能下降:资源加载失败还可能影响页面的整体性能。浏览器在加载资源时会消耗一定的时间和带宽,如果资源加载失败,浏览器可能会尝试重新加载或触发其他回退机制,这都会增加额外的开销和延迟。长时间的加载和重试可能导致页面响应变慢,甚至引发浏览器崩溃等问题。

  4. 安全性风险:在某些情况下,资源加载失败还可能带来安全性风险。例如,如果加载的脚本文件被篡改或注入恶意代码,那么即使加载失败,也可能导致用户设备被攻击或数据泄露。因此,在前端开发中,确保资源的安全性和完整性也是非常重要的。

前端资源加载失败的解决方案

图片加载失败

解决方案:

1. 使用备用图片

<img>标签中设置一个备用图片地址,在原始图片加载失败时显示备用图片。

<img src="original-image.jpg" onerror="this.src='backup-image.jpg'">

2. 图片加载状态监测

通过JavaScript,可以监测图片的加载状态,如果加载失败,则执行相应的处理逻辑。

var img = new Image();
img.onload = function({
  // 图片加载成功后的操作
};
img.onerror = function({
  // 图片加载失败后的操作
  this.src = 'backup-image.jpg'// 加载备用图片
};
img.src = 'original-image.jpg';

3. CSS背景图片备用方案

在CSS中使用背景图片时,也可以通过设置多个背景图片来实现备用图片的显示。

.element {
  background-imageurl('original-image.jpg'), url('backup-image.jpg');
}

4. 图片加载失败通知

当图片加载失败时,还可以向用户展示一些通知,比如替代文本或者特定的UI元素,以便用户得知图片未能正确加载。

<img src="image.jpg" alt="Image Description">
<p>如果图片无法加载,将显示此消息。</p>

CSS 文件加载失败

解决方案:

1. 使用备用CSS链接

<link>标签中设置备用的CSS链接,在原始CSS加载失败时加载备用的CSS文件。

<link rel="stylesheet" href="styles.css" onerror="this.href='backup-styles.css'">

2. CSS加载状态监测

通过JavaScript,可以监测CSS文件的加载状态,如果加载失败,则执行相应的处理逻辑。

var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'styles.css';
link.onerror = function({
  // CSS加载失败后的操作
  this.href = 'backup-styles.css'// 加载备用CSS文件
};
document.head.appendChild(link);

3. 页面结构优雅降级

可以考虑在CSS加载失败时对页面结构进行降级,确保页面内容仍能够正常显示。

<!-- 在<head>中内联备用CSS代码 -->
<style>
  /* 备用样式 */
</style>

JS资源加载失败的解决方案

解决方案:

  1. 使用CDN备份:

使用CDN备份可以在主CDN出现故障或资源加载失败时,提供备用的资源加载路径。

以下是如何使用备用CDN链接来解决lazy.js加载失败的问题:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lazy Load Example</title>
    <script>
        window.onload = function({
            var mainCDN = 'https://cdnjs.cloudflare.com/ajax/libs/lazy/1.7.1/lazy.min.js';
            var backupCDN = 'https://unpkg.com/lazy@1.7.1/dist/lazy.min.js';
            // 尝试加载主CDN
            var script = document.createElement('script');
            script.src = mainCDN;
            script.async = true;
            script.onload = function({
                console.log('lazy.js loaded successfully from main CDN.');
            };
            script.onerror = function({
                console.error('Failed to load lazy.js from main CDN, falling back to backup.');
                // 加载失败,切换到备用CDN
                script.src = backupCDN;
            };
            document.head.appendChild(script);
        };
    
</script>
</head>
<body>
    <!-- 页面内容 -->
</body>
</html>

注意:

  • 使用SRI(Subresource Integrity):这可以确保即使从CDN加载资源,其内容也是完整且未被篡改的。
  • 缓存策略:合理配置缓存策略,以减少对CDN的依赖并提高加载速度。

2. 延迟加载和异步加载:

使用延迟加载或异步加载脚本可以避免因某个 JavaScript 文件加载失败而阻塞整个页面加载过程。例如,在页面底部添加如下代码:

<script>
  function downloadJSAtOnload({
    var element = document.createElement("script");
    element.src = "deferred-script.js";
    document.body.appendChild(element);
  }
  if (window.addEventListener) {
    window.addEventListener("load", downloadJSAtOnload, false);
  } else if (window.attachEvent) {
    window.attachEvent("onload", downloadJSAtOnload);
  } else {
    window.onload = downloadJSAtOnload;
  }
</script>

3. 捕获并处理错误:

使用 window.onerror 全局事件来捕获 JavaScript 错误,然后根据需要执行相应的错误处理逻辑,比如记录到日志中或者展示用户友好的错误信息。

4. 加载重试

4.1. 监听加载失败事件

在HTML中,为<script>标签添加onerror事件监听器:

<script src="course-player.js" onerror="retryLoadScript('course-player.js', 3)"></script>
4.2. 重试加载函数
let retryCount = 0;
const maxRetries = 3// 最大重试次数
const retryInterval = 2000// 每次重试间隔2秒

function retryLoadScript(scriptSrc, retriesLeft{
    if (retriesLeft <= 0) {
        // 达到最大重试次数,显示错误或回退方案
        console.error('Failed to load script after multiple retries:', scriptSrc);
        // 可以在这里添加回退逻辑,比如显示一个错误消息给用户
        return;
    }

    // 清除之前的script标签(如果有的话)
    const existingScript = document.querySelector(`script[src="${scriptSrc}"]`);
    if (existingScript) {
        existingScript.remove();
    }

    // 创建新的script标签并设置src属性
    const script = document.createElement('script');
    script.src = scriptSrc;
    script.async = true// 异步加载

    // 监听新的加载失败事件
    script.onerror = function({
        retryCount++;
        console.log(`Retrying to load script ${scriptSrc}, attempt ${retryCount}`);
        setTimeout(function({
            retryLoadScript(scriptSrc, retriesLeft - 1); // 递归调用,重试次数减一
        }, retryInterval);
    };

    // 监听加载成功事件(可选)
    script.onload = function({
        console.log('Script loaded successfully:', scriptSrc);
    };

    // 将新的script标签添加到DOM中
    document.head.appendChild(script);
}
4.3. 在页面中使用回退逻辑

如果重试加载仍然失败,可以在retryLoadScript函数中实现一些回退逻辑。例如,可以显示一个错误消息给用户,或者提供一个备用的加载机制。

注意:
  • 确保不要过度重试,以免给服务器造成不必要的负担。
  • 根据项目的实际情况调整重试次数和间隔。
  • 对于非关键资源,可以考虑使用更轻量级的错误处理策略,比如简单地记录日志并忽略错误。

最后

还没有使用过我们刷题网站(https://fe.ecool.fun/)或者前端面试题宝典的同学,如果近期准备或者正在找工作,千万不要错过,我们的题库主打无广告和更新快哦~。

老规矩,也给我们团队的辅导服务打个广告。