【问题标题】:How to check whether user has internet connection or not in Angular2?如何在Angular2中检查用户是否有互联网连接?
【发布时间】:2017-01-27 00:41:26
【问题描述】:

我将如何在 API 命中时检查 Angular2 中的互联网连接,每当在我的应用程序 API 中命中服务器时,有时用户是 离线(我的意思是没有互联网连接)那么我将如何检查互联网连接?互联网连接是否有一些特殊的状态代码? 还是别的什么?

PS:- 我在 angularJs 中找到了 navigator.onLine,但似乎在 angular2 中不起作用。

更新

正如 sudheer 在navigator.onLine 下面的回答中建议的那样,使用 angular2 但仍然无法正常工作,为什么? working example here

【问题讨论】:

  • 我使用 Windows 10 和 Chrome 进行了检查。如果至少连接了一个网络适配器,它总是返回“真”。所以如果你安装了一个虚拟适配器,比如 VirtualBox 中的“HostOnly-Network”,你总是会得到“真”,直到你也禁用它。 :(

标签: http angular


【解决方案1】:
import { Injectable } from '@angular/core';
import {
    HttpRequest,
    HttpHandler,
    HttpEvent,
    HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class InternetInterceptor implements HttpInterceptor {
    constructor() { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // check to see if there's internet
        if (!window.navigator.onLine) {
            // if there is no internet, throw a HttpErrorResponse error
            // since an error is thrown, the function will terminate here
            return Observable.throw(new HttpErrorResponse({ error: 'Internet is required.' }));

        } else {
            // else return the normal request
            return next.handle(request);
        }
    }
}

【讨论】:

  • 请始终在回答中描述您在做什么。它应该被更新或删除。在提供更多答案之前阅读How to answer ^^
【解决方案2】:

对于 Angular 9 - 一个非常简单且使用舒适的解决方案(感谢 thisthis 解决方案):

1) 创建新组件:

ng g c NoConnection

no-connection.component.ts

import { Component, OnInit } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'
import { HttpClient }    from '@angular/common/http';

@Component({
  selector: 'app-no-connection',
  templateUrl: './no-connection.component.html',
  styleUrls: ['./no-connection.component.css']
})
export class NoConnectionComponent implements OnInit {

  isConnectionAvailable: boolean = navigator.onLine; 

  constructor(private httpClient: HttpClient) { 
      window.addEventListener('online', () => {
        this.isConnectionAvailable = true
    });

    window.addEventListener('offline', () => {
        this.isConnectionAvailable = false
    });
  }

  ngOnInit(): void {
  }

}

no-connection.component.html(根据需要自定义页面)

<div>

    <p style.color = "{{ isConnectionAvailable  ? 'green' : 'red'}}"> {{ isConnectionAvailable  ? 'Online' : 'Offline'}} </p>  

    <!-- https://stackoverflow.com/questions/13350663/greyed-out-waiting-page-in-javascript#answer-13350908 -->
    <div id="blackout" class="noselect" style.display = "{{isConnectionAvailable ? 'none' : 'block'}}">
        <br><br><br><br><br>
        <p>No Internet connection!</p>
        <br>
    </div>

</div>

no-connection.component.css

#blackout {
    width:100%;
    height:100%; /* make sure you have set parents to a height of 100% too*/
    position: absolute;
    left:0; top:0;
    z-index:10; /*just to make sure its on top*/

    opacity: 0.5; 
    background-color:#333; 
    text-align: center;

    font-size:25px; 
    color: white;
}

.noselect {
  -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
     -khtml-user-select: none; /* Konqueror HTML */
       -moz-user-select: none; /* Old versions of Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome, Opera and Firefox */                               
}

2) 在任何你想要的地方使用它——在我的例子中最好的地方——是一个根组件:

app.component.html

<div>

    <app-no-connection></app-no-connection>

    <app-main></app-main>

</div> 

【讨论】:

    【解决方案3】:

    (2018) 为 rxjs6 更新代码

    它完全适用于 angular2。显然它与 angularJS 不同,因为 $scope 和 $apply 都不存在了。不过,RxJS 让这一切变得简单!在 Chrome 53 上测试:

    模板:

    <p>{{online$ | async}}</p>
    

    组件:

    import { Observable, fromEvent, merge, of } from 'rxjs';
    import { mapTo } from 'rxjs/operators';
    
    @Component({ /* ... */ })
    export class MyComponent {
      online$: Observable<boolean>;
    
      constructor() {
        this.online$ = merge(
          of(navigator.onLine),
          fromEvent(window, 'online').pipe(mapTo(true)),
          fromEvent(window, 'offline').pipe(mapTo(false))
        );
      }
    }
    

    想想“离线”对您的用例意味着什么!

    未插入的以太网电缆和 3KB/s EDGE 连接可能对您的应用具有相同的影响,尽管后者意味着您在技术上并未离线

    从程序员的角度来看,以非常差的信号进行无线连接实际上比真正断开连接要糟糕得多,因为它更难检测!

    上面的代码返回一个false 值意味着你完全离线,就像断开连接一样。返回true 并不一定表明存在实际可用的连接。

    【讨论】:

    • 总是返回true 为什么会这样?
    • 不知道。它完全适合我。你确定,你离线了吗?
    • 我认为我做错了什么,请您详细说明您的答案
    • 它可以做类似的事情,但是如果这个 url 是活动的,检查一个 API URL 像 api.myapi.com/status 那里返回是 Online ?
    • 嘿@j2L4e 看看这里plnkr.co/edit/Rvjmsg6hDzqOTdwrtP0i?p=preview,我再次尝试了你的代码,但这只会工作一次而不是立即将值切换到TRUE,无法弄清楚为什么?你能帮帮我吗?
    【解决方案4】:

    监听网络状态的安全方法

    上面给出的答案效果很好,但不被认为是安全的方法。

    1. 不应该直接引用窗口等浏览器依赖对象,始终检查平台。

    2. 网络连接等更多功能必须封装到服务中。

    下面是可以订阅监听网络状态的 ConnectionService。它遵循 rxjs 6 风格。

    完整代码

    import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
    import { Observable, fromEvent, merge, empty } from 'rxjs';
    import { isPlatformBrowser } from '@angular/common';
    import { mapTo } from 'rxjs/operators';
    
    @Injectable({
      providedIn: 'root'
    })
    export class ConnectionService {
    
      private connectionMonitor: Observable<boolean>;
    
      constructor(@Inject(PLATFORM_ID) platform) {
    if (isPlatformBrowser(platform)) {
      const offline$ = fromEvent(window, 'offline').pipe(mapTo(false));
      const online$ = fromEvent(window, 'online').pipe(mapTo(true));
      this.connectionMonitor = merge(
        offline$, online$
      );
    } else {
      this.connectionMonitor = empty();
    }
    
    
    
     }
    
      monitor(): Observable<boolean> {
        return this.connectionMonitor;
      }
    }
    

    在组件中,您可以通过订阅 monitor() 或使用异步管道直接进入 HTML 来收听。

    【讨论】:

      【解决方案5】:

      使用这个简单的 Hack。

      在 Angular 5 或更高版本中工作

       constructor(){
          setInterval(()=>{
             if(navigator.onLine){
               //here if it is online
             }else{
              //here if it is offline
             }
          }, 100)
       }
      

      在 app.component.ts 的构造函数或你的应用引导程序中写入 不需要任何外部库..

      【讨论】:

      • 已经有很多相同内容的答案了,这有什么新的?
      【解决方案6】:

      使用 Angular 6+Rxjs 6+,您可以通过以下方式完成:

      import { Observable, fromEvent, merge, of } from 'rxjs';
      import { mapTo } from 'rxjs/operators';
      
      online$: Observable<boolean>;
      
      constructor() {
        this.online$ = merge(
          of(navigator.onLine),
          fromEvent(window, 'online').pipe(mapTo(true)),
          fromEvent(window, 'offline').pipe(mapTo(false))
        )
      }
      

      这是demo(在开发工具中切换网络)

      【讨论】:

      • 如果您提供 stackblitz 等的工作示例会更好,无论如何谢谢,我也会尝试这个:)
      • 这正是@Darth_Evil 回复的方式
      • @candidJ 不完全是,注意语法差异和pipe()的用法
      • @Und3rTow 我明白你的意思,兄弟。我的意思是逻辑是相似的;只使用RxJS 6
      • 关闭我的互联网连接时它不会改变,它在 stackblitz 或我的应用程序中不起作用
      【解决方案7】:

      使用这个。

      没有任何外部库。

      public isOnline: boolean = navigator.onLine;
      
      ngOnInit() { 
          console.log(this.isOnline); 
      }
      

      【讨论】:

      • 这正是@sudheerKb 提到的。
      【解决方案8】:

      起初,j2L4e 的答案对我不起作用(在 Chrome 中测试)。我通过在 ngIf 中将我的 bool 括在括号中进行了微调,这最终起作用了。

      &lt;md-icon class="connected" mdTooltip="No Connection" *ngIf="!(isConnected | async)"&gt;signal_wifi_off&lt;/md-icon&gt;

      import { Component, OnInit } from '@angular/core';
      import { Observable } from 'rxjs/Observable';
      import { Subscription } from 'rxjs/Subscription';
      import 'rxjs/Rx';
      
      @Component({
        selector: 'toolbar',
        templateUrl: './toolbar.component.html',
        styleUrls: ['./toolbar.component.css']
      })
      export class ToolbarComponent implements OnInit {
        isConnected: Observable<boolean>;
      
        constructor() {
          this.isConnected = Observable.merge(
            Observable.of(navigator.onLine),
            Observable.fromEvent(window, 'online').map(() => true),
            Observable.fromEvent(window, 'offline').map(() => false));
        }
      
        ngOnInit() {
      
        }
      }
      

      【讨论】:

      • 为什么要导入 'rxjs/Rx' 库。这是巨大而糟糕的做法。此外,Observable 和 Subscription 已经导入。
      • 它始终处于连接状态!已连接标志始终为真(在最新的 chrome 版本上),不知道为什么状态没有改变!
      【解决方案9】:

      我已经检查过导航器是像窗口这样的全局对象。您可以在 angular2 中使用,它对我来说效果很好。

      import {Component} from 'angular2/core';
      @Component({
          selector: 'my-app',
          template:`
      navigator.onLine
      {{onlineFlag}}
      
      `
      })
      export class AppComponent {
        public onlineFlag =navigator.onLine;
      }
      

      【讨论】:

      • 在这个例子中工作正常。请查看here
      • 如何在离线模式下查看 plunker? (在离线模式下,如果我做了一些更改,则页面无法刷新,所以我无法检查)
      • 先用互联网运行代码,然后断开互联网连接并检查值,现在您将看到值反映。
      • 当我第一次删除连接值更改为false,但随后值立即更改为true,没有插入互联网连接,我可以知道是什么原因吗?
      • 对我来说工作得很好。我正在检查 Chrome 最新版本。请检查您的浏览器一次
      猜你喜欢
      • 2019-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多