Angular 网络连接状态组件

Posted 全栈修仙之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Angular 网络连接状态组件相关的知识,希望对你有一定的参考价值。

在开发 Web 应用程序时,有时候我们需要获取当前的网络状态,然后根据不同的网络状态显示不同的提示消息或显示不同页面内容。对于原生应用、混合应用或提供 JS-SDK 的第三方平台来说,我们可以通过相关的 Network API 来获取当前的网络连接状态。但对于 Web 应用来说,虽然也有相关的 Network Information API,但兼容性并不是太好,具体的兼容情况,可以参考 Can I Use - netinfo。

Network Information API

此 API 是由 WICG 编辑的草案,目前可在 Chrome 61 以上的版本中使用。开发者可以通过navigator.connection对象来访问与当前网络连接相关的属性:

  • connection.type:返回当前 User Agent 的物理网络类型,可能的值为 “cellular”,”ethernet”,”wfi” 或 “none” 等;

  • connection.downlink:返回基于最近观察到的活动连接的有效带宽(以 Mb/s 为单位);

  • connection.rtt:返回基于最近观察到的活动连接估计平均往返时间(以毫秒为单位);

  • connection.saveData:如果用户在其浏览器启用 “reduced data mode” 模式,则返回 true;

  • connection.effectiveType:返回有效的网络连接类型,可能的值为 slow-2g,2g,3g 或 4g。该值的是基于 rtt 和 downlink 的值测算出来的。


以下是网络连接类型的评估标准:

讲到这里突然想起之前看到的一篇文章 JS 检测网络带宽,有兴趣的小伙伴可以了解一下。

开发网络连接组件

通过结合 Network Information API 与 Angular,我们可以创建一个组件,实现根据不同网络连接速度渲染不同的内容。比如,当我们检测到弱网络的时候,我们可以渲染一个占位符或一个低分辨率的图片或视频,从而提高页面的加载速度。

首先,让我们把连接变化事件封装为一个 Observable 对象:

const connection$ = new Observable((observer) => {

 
const { effectiveType } = navigator.connection;
 observer
.next(effectiveType);
 
const onConnectionChange = () => {
   
const { effectiveType } = navigator.connection;
   observer
.next(effectiveType);
 
}
 navigator
.connection
   .addEventListener('change', onConnectionChange)
 
return () => {
   navigator
.connection
     
.removeEventListener('change', onConnectionChange);
   observer
.complete();
 
}
});

在页面初始化和连接网络状态发生变化的时候,可观察的 connection$ 对象将会自动通知我们当前的网络连接状态。

接下来,我们来创建 ConnectionComponent 组件和相关的 Connection 指令:

connection.component.ts

@Component({
 selector
: 'connection',
 
template: `
   <ng-template [ngTemplateOutlet]="fast.tpl"
      *ngIf="isFast">
   </ng-template>    <ng-template [ngTemplateOutlet]="slow.tpl"
      *ngIf="!isFast">
   </ng-template>  `
,
})
export class ConnectionComponent {
 isFast
= true;
 
@ContentChild(FastDirective)
    fast
: FastDirective;
 
@ContentChild(SlowDirective)
    slow
: SlowDirective;
 
private subscription: Subscription;
 ngOnInit
() {
   
const connection = navigator.connection;
   
if (!connection) {
     
return;
   
}
   
this.subscription = connection$
     
.subscribe((effectiveType: string) => {
       
if (/slow-2g|2g|3g/.test(effectiveType)) {
         
this.isFast = false;
       
} else {
         
this.isFast = true;
       
}
     
})
 
}
 ngOnDestroy
() {
   
this.subscription
     && this.subscription.unsubscribe();
 
}
}

fast.directive.ts

@Directive({
 selector
: '[fast]'
})
export class FastDirective {
 constructor
(
   public tpl: TemplateRef<any>
 ) { }
}

slow.directive.ts

@Directive({
 selector
: '[slow]'
})
export class SlowDirective {
constructor
(
 
public tpl: TemplateRef<any>
) { }
}

在上面的示例中,ConnectionComponent 会根据 effectiveType 属性的值,然后显示 slow 或 fast 指令实例所关联的模板。现在我们来看一下如何使用:

<connection>
 
<ng-container *fast>
   Fast connection - Render a video  
 </ng-container>
 
<ng-container *slow>
   Slow connection - Render a placeholder  
 </ng-container>
</connection>

正如前面提到的,基于 Network Information API ,我们也可以实现一个简单的指令,根据不同的网络状态显示不同分辨率的图片。

<img connection
   
slowSrc="https://via.placeholder.com/350x150?text=slow"
   
fastSrc="https://via.placeholder.com/350x150?text=fast">

对应的 connection 指令的具体实现如下:

import { Directive, Attribute, ElementRef } from '@angular/core';

@Directive({
 selector
: '[connection]'
})
export class ConnectionDirective {
 constructor
(
   @Attribute('slowSrc')
     
private slowSrc,
   
@Attribute('fastSrc')
     
private fastSrc,
   
private host: ElementRef<htmlImageElement>
 
) {
 
}
 ngOnInit
() {
   
const { effectiveType } = navigator.connection;
   
let src;
   
if (/slow-2g|2g|3g/.test(effectiveType)) {
     src
= this.slowSrc;
   
} else {
     src
= this.fastSrc;
   
}
   
this.host.nativeElement.setAttribute('src', src)
 
}
}

查看线上完整的示例:Stackblitz

总结

本文是在过完 “10·24 — 爱码士” 节后,参考 connection-aware-components-in-angular 这篇文章整理的。其中主要介绍了 Network Information API 涉及的相关属性及每个属性的作用。对于使用 Ionic 或 Cordova 项目来说,可以使用 cordova-plugin-network-information 这个库来获取网络信息,有需要的小伙伴可以了解一下。

参考资源

  • connection-aware-components-in-angular

  • connection-aware-components

以上是关于Angular 网络连接状态组件的主要内容,如果未能解决你的问题,请参考以下文章

Android导航组件:如何保存片段状态

angularjs2 学习笔记 组件

如何保存底部导航片段的状态 - 具有单个导航图的 Android 导航组件

当返回到“导航架构组件”中的同一选项卡时,嵌套片段的状态会丢失

如何在 Angular Universal 中捕获服务器上的组件错误?

Angular2路由-路由更改时保持组件状态[重复]