网络信息API结合存储在性能方面的探索

网络信息 API 实现自适应能力

在当下同时有2G、3G、4G、5G等网络条件的情况下,用户对网页的体验也出现了层出不穷的情况。例如在手机上浏览视频网站,能够根据用户当前使用的网络类型,在必要的时候给出提示,是一种很好的体验。

网络信息API结合存储在性能方面的探索_第1张图片

 

从1G到5G的演进

有兴趣的同学可以看一下,一部波澜壮阔的移动通信史

简单的说就是:

1G采用的技术是模拟通信系统。只能用于打电话,短信什么的都不可以;信号不稳定,通话质量差;不同国家通信系统不兼容。

2G能发短信、浏览最简单网页、甚至玩游戏(记得以前玩过一款猫扑网的文字游戏)

3G主要提升了传输数据的速度,3G手机能快速处理图像、音乐、视频等媒体(3G版qq,偷菜)

4G具备速度快、通信质量高、费用便宜等特点,几乎满足了所有用户对于无线服务的需求

5G拥抱未来,超高速传输会给用户带来更好的体验,能提供更多的服务,一切皆有可能

 

简单列举JS在浏览器中判断当前网络连接状态的方法

navigator.onLine

demo:http://html5-demos.appspot.com/static/navigator.onLine.html

通过window.navigator.onLine是否为true来判断当前的网络状态

根据MDN的描述:机器未连接到局域网或路由器时返回false,其他情况下均返回true。

也就是说,机器连接上路由器后,即使这个路由器没联通网络,navigator.onLine仍然返回true。

网络信息API结合存储在性能方面的探索_第2张图片

 

这里做了一个简单的小实验,电脑连接手机热点,此时手机断开流量,电脑无法打开网页,但是navigator.onLine仍然返回true。

除了主动的触发navigator.onLine进行网络状态检测以外,还提供了相关的事件进行监听:  


  function updateOnlineStatus(event) {

    console.log(event)

  }

  window.addEventListener('online',  updateOnlineStatus);

  window.addEventListener('offline', updateOnlineStatus);

可以看到伴随着网络的打开和关闭,会触发相应的事件,我们也可以在回调中去进行我们想要的操作。

同样的,路由器的断网无法侦测到。

兼容性方面是非常好的

https://caniuse.com/#search=online网络信息API结合存储在性能方面的探索_第3张图片

 

获取网络资源

常用的方法是可以创建一张隐藏图片去发送get请求,通过onerror来判断网络是否异常。

Network Information API

Navigator.connection 是只读的,提供一个NetworkInformation 对象来获取设备的网络连接信息。例如用户设备的当前带宽或连接是否被计量, 这可以用于基于用户的连接来选择高清晰度内容或低清晰度内容。

如何应对网络连接质量的变化呢?

https://googlechrome.github.io/samples/network-information/index.html

我们可以通过 connection.onchange 事件监听器来监听网络变化:

function onConnectionChange() {

    const { rtt, downlink, effectiveType,  saveData } = navigator.connection;



    console.log(`Effective network connection type: ${effectiveType}`);

    console.log(`Downlink Speed/bandwidth estimate: ${downlink}Mb/s`);

    console.log(`Round-trip time estimate: ${rtt}ms`);

    console.log(`Data-saver mode on/requested: ${saveData}`);

}



navigator.connection.addEventListener('change', onConnectionChange)

type 返回设备正在与网络进行通信的连接类型

  • bluetooth 蓝牙连接
  • cellular 蜂窝连接
  • ethernet 以太网连接
  • none 无网络连接
  • wifi Wi-Fi连接
  • wimax WiMAX连接

·在概念上类似WiFi,WiMAX传送速率更快,传送范围距离更大,简单理解为一种“大WiFi”。

  • other 已知的连接类型,但不是枚举连接类型之一。
  • unknown 用户代理已建立网络连接,但无法或不愿确定基础连接技术。

downlink 有效带宽估计

该属性表示基于最近观察到的活动连接的有效带宽估计值(以Mb / s为单位)。

effectiveType

effectiveType 可取值有 'slow-2g'、'2g'、'3g' 或者 '4g'。在网速慢的时候,此功能可以让你通过提供较低质量的资源来提高页面的加载速度。

enum EffectiveConnectionType {

  "2g",

  "3g",

  "4g",

  "slow-2g"

};

rtt来回通信延迟

在通信(Communication)、电脑网络(Computer network)领域中,意指:在双方通信中,发讯方的信号(Signal)传播(Propagation)到收讯方的时间(意即:传播延迟(Propagation delay)),加上收讯方回传消息到发讯方的时间(如果没有造成双向传播速率差异的因素,此时间与发讯方将信号传播到收讯方的时间一样久)

saveData

https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/save-data

正确解决用户对快速轻便的应用程序和页面的高需求,一种相当简单的技术是让浏览器使用Save-Data请求标头提供帮助 。通过标识此标头,网页可以自定义并向受成本和性能限制的用户提供最佳的用户体验。

兼容性

大体看来Chrome对它的兼容性会较好一些,其他的浏览器兼容性参差不齐,不过,它是渐进式增强的一个很好的候选者,并且对其他平台的支持也在不断增加。

https://caniuse.com/#search=NetworkInformation网络信息API结合存储在性能方面的探索_第4张图片

网络感知组件https://codepen.io/mxbck/pen/JZxyoa?editors=0010


function withConnectionType(WrappedComponent, respondToChange = false) {

    return class extends React.Component {

        constructor(props) {

            super(props)

            this.state = {

                connectionType: undefined

            }

            // Basic API Support Check.

            this.hasNetworkInfoSupport = Boolean(

                navigator.connection && navigator.connection.effectiveType

            )

            this.setConnectionType = this.setConnectionType.bind(this)

        }



        componentWillMount() {

            // Check before the component first renders.

            this.setConnectionType()

        }



        componentDidMount() {

            // optional: respond to connectivity changes.

            if (respondToChange) {

                navigator.connection.addEventListener(

                    'change', 

                    this.setConnectionType

                )

            }

        }



        componentWillUnmount() {

            if (respondToChange) {

                navigator.connection.removeEventListener(

                    'change', 

                    this.setConnectionType

                )

            }

        }



        getConnectionType() {

            const connection = navigator.connection

            // check if we're offline first...

            if (!navigator.onLine) {

                return 'offline'

            }

            // ...or if reduced data is preferred.

            if (connection.saveData) {

                return 'saveData'

            }

            return connection.effectiveType

        }



        setConnectionType() {

            if (this.hasNetworkInfoSupport) {

                const connectionType = this.getConnectionType()

                this.setState({

                    connectionType

                })

            }

        }



        render() {

            // inject the prop into our component.

            // default to "undefined" if API is not supported.

            return (

                

            )

        }

    }

}



// Now we can reuse the function to enhance all kinds of components.

const ConnectionAwareMedia = withConnectionType(Media)

 

结合localForage的增强体验

localForage 是一个 JavaScript 库,通过简单类似 localStorage API 的异步存储来改进你的 Web 应用程序的离线体验。它能存储多种类型的数据,而不仅仅是字符串。

localForage 有一个优雅降级策略,若浏览器不支持 IndexedDB 或 WebSQL,则使用 localStorage。在所有主流浏览器中都可用:Chrome,Firefox,IE 和 Safari(包括 Safari Mobile)。

默认情况下,localForage 按照以下顺序选择数据仓库的后端驱动:

  1. IndexedDB
  1. WebSQL
  1. localStorage

浏览器本地存储的大小测试

http://dev-test.nemikor.com/web-storage/support-test/

getItem(key, successCallback)

localforage.getItem('somekey').then(function(value) {

    // 当离线仓库中的值被载入时,此处代码运行

    console.log(value);

}).catch(function(err) {

    // 当出错时,此处代码运行

    console.log(err);

});



// 回调版本:

localforage.getItem('somekey', function(err, value) {

    // 当离线仓库中的值被载入时,此处代码运行

    console.log(value);

});

setItem(key, value, successCallback)

将数据保存到离线仓库。你可以存储如下类型的 JavaScript 对象:

Array、ArrayBuffer、Blob、Float32Array、Float64Array、Int8Array、Int16Array、Int32Array、Number、Object、Uint8Array、Uint8ClampedArray、Uint16Array、Uint32Array、String


localforage.setItem('somekey', 'some value').then(function (value) {

    // 当值被存储后,可执行其他操作

    console.log(value);

}).catch(function(err) {

    // 当出错时,此处代码运行

    console.log(err);

});



// 不同于 localStorage,你可以存储非字符串类型

localforage.setItem('my array', [1, 2, 'three']).then(function(value) {

    // 如下输出 `1`

    console.log(value[0]);

}).catch(function(err) {

    // 当出错时,此处代码运行

    console.log(err);

});



// 你甚至可以存储 AJAX 响应返回的二进制数据

req = new XMLHttpRequest();

req.open('GET', '/photo.jpg', true);

req.responseType = 'arraybuffer';



req.addEventListener('readystatechange', function() {

    if (req.readyState === 4) { // readyState 完成

        localforage.setItem('photo', req.response).then(function(image) {

            // 如下为一个合法的  标签的 blob URI

            var blob = new Blob([image]);

            var imageURI = window.URL.createObjectURL(blob);

        }).catch(function(err) {

          // 当出错时,此处代码运行

          console.log(err);

        });

    }

});

removeItem(key, successCallback)

localforage.removeItem('somekey').then(function() {

    // 当值被移除后,此处代码运行

    console.log('Key is cleared!');

}).catch(function(err) {

    // 当出错时,此处代码运行

    console.log(err);

});

clear(successCallback)

localforage.clear().then(function() {

    // 当数据库被全部删除后,此处代码运行

    console.log('Database is now empty.');

}).catch(function(err) {

    // 当出错时,此处代码运行

    console.log(err);

});

IndexedDB 浏览器存储限制和清理标准

储存限制

浏览器的最大存储空间是动态的——它取决于硬盘大小。

全局限制——可用磁盘空间的50%。 如果您的硬盘驱动器是500GB,那么浏览器的总存储容量为250GB。如果超过此范围,则会发起称为源回收的过程,删除整个源的数据,直到存储量再次低于限制。删除源数据没有只删一部分的说法——因为这样可能会导致不一致的问题。

组限制——这被定义为全局限制的20%,但它至少有10 MB,最大为2GB。 每个源都是一组(源组)的一部分。 每个eTLD+1域都有一个组。 例如:

​mozilla.org​——组1,源1
​www.mozilla.org​——组1,源2
​joe.blogs.mozilla.org​——组1,源3
​firefox.com​ ——组2,源4
在这个组中,​mozilla.org​、​www.mozilla.org​和​joe.blogs.mozilla.org​可以聚合使用最多20%的全局限制。 ​firefox.com​单独最多使用20%。

达到限制后有两种不同的反应:

  • 组限制也称为“硬限制”:它不会触发源回收,如果超出,浏览器将抛出​QuotaExceededError​错误。
  • 全局限制是一个“软限制”,因为其有可能释放一些空间并且这个操作可能持续。

LRU策略

https://developers.google.com/web/updates/2011/11/Quota-Management-API-Fast-Facts

当可用磁盘空间已满时,配额管理器将根据LRU策略开始清除数据——最近最少使用的源将首先被删除,然后是下一个,直到浏览器不再超过限制。

使用临时存储跟踪每个源的“上次访问时间”。 一旦达到临时存储的全局限制(之后会有更多限制),系统将尝试查找所有当前未使用的源(即没有打开选项卡/应用程序的那些来保持打开的数据存储)。 然后根据“上次访问时间”对它们进行排序。 然后删除最近最少使用的源,直到有足够的空间来满足触发此源回收的请求。

总结

通过网络感知提供一个自适应的能力,结合离线存储方案以及渐进式体验等方式,在当下网络质量参差不齐的情况下,可以更好的增强用户体验。

你可能感兴趣的:(优化与兼容)