Skip to content

前端如何区分弱网加载不同资源场景 #127

@pfan123

Description

@pfan123

前端如何区分弱网加载不同资源

在前端区分弱网并加载不同资源,可从以下几个方面实现:

1. 网络状态检测

  • navigator.connection API:这是一个相对新的API,可获取网络连接信息。
if ('connection' in navigator) {
    const connection = navigator.connection;
    connection.addEventListener('change', () => {
        if (connection.effectiveType === '4g') {
            // 高速网络,加载高清资源
            loadHighQualityResources();
        } else if (connection.effectiveType === '3g') {
            // 中等网络,加载中等质量资源
            loadMediumQualityResources();
        } else if (connection.effectiveType === '2g') {
            // 弱网,加载低质量资源
            loadLowQualityResources();
        }
    });
}
  • 通过心跳检测:定期向服务器发送请求,根据响应时间判断网络状况。
function checkNetwork() {
    const startTime = new Date().getTime();
    fetch('/ping')
      .then(response => {
            const endTime = new Date().getTime();
            const latency = endTime - startTime;
            if (latency > 1000) {
                // 网络延迟较高,可能是弱网
                loadLowQualityResources();
            } else {
                // 网络较好,加载高质量资源
                loadHighQualityResources();
            }
        })
      .catch(() => {
            // 请求失败,可能是弱网或无网络
            loadLowQualityResources();
        });
}
setInterval(checkNetwork, 5000);

2. 资源加载策略

  • 图片资源:可利用<picture>标签结合srcset属性,根据网络状况加载不同分辨率图片。
<picture>
    <source media="(max-width: 600px) and (connection: slow-2g)" srcset="low-res-mobile.jpg">
    <source media="(connection: slow-2g)" srcset="low-res.jpg">
    <source media="(connection: 2g)" srcset="medium-res.jpg">
    <img src="high-res.jpg" alt="image">
</picture>
  • 视频资源:使用<video>标签的srcset属性类似方法,或借助视频播放器的自适应流技术(如HLS、MPEG - DASH),播放器会根据网络实时调整视频质量。
<video controls>
    <source src="low - quality.mp4" media="(connection: slow - 2g)">
    <source src="medium - quality.mp4" media="(connection: 2g)">
    <source src="high - quality.mp4">
</video>
  • 脚本和样式表:根据网络状况,动态加载不同版本的脚本或样式表。
function loadScripts() {
    if (isWeakNetwork) {
        const script = document.createElement('script');
        script.src = 'light - script.js';
        document.head.appendChild(script);
    } else {
        const script = document.createElement('script');
        script.src = 'full - script.js';
        document.head.appendChild(script);
    }
}

用户网络状态是不固定的,出现误判怎么优化

当考虑到用户网络状态不固定且可能出现误判时,可从以下几个方面进行优化:

1. 多维度检测

  • 结合多种检测方法:不要仅依赖单一的网络检测方式。例如,同时使用 navigator.connection API 和心跳检测。navigator.connection 能实时获取网络连接类型,但在某些环境可能不够准确;心跳检测虽有延迟,但可从实际网络请求响应时间补充判断。
let networkStatus = 'unknown';
if ('connection' in navigator) {
    const connection = navigator.connection;
    connection.addEventListener('change', () => {
        networkStatus = connection.effectiveType;
        if (networkStatus === '2g' || networkStatus ==='slow - 2g') {
            checkHeartbeat();
        }
    });
}

function checkHeartbeat() {
    const startTime = new Date().getTime();
    fetch('/ping')
      .then(response => {
            const endTime = new Date().getTime();
            const latency = endTime - startTime;
            if (latency > 1000) {
                // 确认是弱网
                handleWeakNetwork();
            } else {
                // 网络可能较好,重新评估
                handleGoodNetwork();
            }
        })
      .catch(() => {
            // 网络不稳定或弱网
            handleWeakNetwork();
        });
}
  • 参考设备信息:不同设备的网络性能也有差异。比如移动设备在信号不好时更容易出现弱网。可通过 navigator.userAgent 获取设备信息辅助判断。
const userAgent = navigator.userAgent.toLowerCase();
const isMobile = /mobile|android|iphone|ipad|ipod/.test(userAgent);
if (isMobile && (networkStatus === '2g' || networkStatus ==='slow - 2g')) {
    // 对移动设备的弱网处理更谨慎
    handleWeakNetworkMoreCarefully();
}

2. 动态调整与平滑过渡

  • 实时监测与调整:持续监测网络状态变化,当网络状态发生改变时,及时调整资源加载策略。例如,从弱网变为强网时,立即停止加载低质量资源,转而加载高质量资源。
if ('connection' in navigator) {
    const connection = navigator.connection;
    connection.addEventListener('change', () => {
        if (connection.effectiveType === '4g') {
            if (isLoadingLowQuality) {
                cancelLowQualityLoading();
                loadHighQualityResources();
            }
        } else if (connection.effectiveType === '2g' || connection.effectiveType ==='slow - 2g') {
            if (isLoadingHighQuality) {
                cancelHighQualityLoading();
                loadLowQualityResources();
            }
        }
    });
}
  • 平滑过渡:在资源切换时,避免突兀。对于图片,可以使用淡入淡出效果;对于视频,在切换质量时,设置短暂的缓冲提示,告知用户正在调整。
<img id="myImage" src="low - res.jpg" alt="image">
<script>
    function switchImageQuality() {
        const img = document.getElementById('myImage');
        img.style.opacity = '0';
        setTimeout(() => {
            img.src = 'high - res.jpg';
            img.style.opacity = '1';
        }, 300);
    }
</script>

3. 用户反馈机制

  • 提供反馈入口:在应用中设置反馈按钮,让用户能主动告知网络状态与加载情况不符。例如,用户觉得网络很好,但却加载了低质量资源,可通过反馈入口告知开发者。
<button id="networkFeedbackButton">反馈网络问题</button>
<script>
    const feedbackButton = document.getElementById('networkFeedbackButton');
    feedbackButton.addEventListener('click', () => {
        const userFeedback = prompt('请描述网络状态与加载资源不符的情况');
        // 将反馈信息发送给服务器
        fetch('/feedback', {
            method: 'POST',
            headers: {
                'Content - Type': 'application/json'
            },
            body: JSON.stringify({ userFeedback })
        });
    });
</script>
  • 根据反馈优化算法:收集用户反馈数据,分析误判场景,针对性地调整网络检测和资源加载策略的算法,提高判断准确性。

4. 智能预加载与缓冲

  • 智能预加载:根据用户行为和页面结构,提前预加载可能需要的资源。例如,用户在浏览文章时,提前预加载下一篇文章可能用到的图片和脚本,并且根据当前网络状态预加载合适质量的资源。
function preloadNextPageResources() {
    if (networkStatus === '4g') {
        preloadHighQualityResourcesForNextPage();
    } else if (networkStatus === '2g' || networkStatus ==='slow - 2g') {
        preloadLowQualityResourcesForNextPage();
    }
}
  • 自适应缓冲:对于视频等资源,根据网络波动动态调整缓冲区大小。在网络不稳定时,适当增加缓冲区,防止播放卡顿。可通过视频播放器的 API 实现,如 HTML5 视频的 buffering 事件。
<video id="myVideo" controls>
    <source src="video.mp4" type="video/mp4">
</video>
<script>
    const video = document.getElementById('myVideo');
    video.addEventListener('buffering', () => {
        if (networkStatus === '2g' || networkStatus ==='slow - 2g') {
            // 弱网时增加缓冲区
            video.buffered.max();
        }
    });
</script>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions