Angular中如何通过HttpInterceptor实现无网络时显示自定义组件
解决方案
你可以通过全局共享状态服务的方式,在拦截器中更新网络状态,所有需要感知网络状态的组件直接订阅服务即可,不需要每个组件单独做网络检测。
实现步骤
- 第一步:创建全局网络状态共享服务
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class NetworkStatusService { // 初始值取当前设备的网络状态 private isOnlineSub = new BehaviorSubject<boolean>(window.navigator.onLine); // 对外暴露可订阅的状态流 public isOnline$ = this.isOnlineSub.asObservable(); // 更新网络状态 setOnlineStatus(status: boolean) { this.isOnlineSub.next(status); } constructor() { // 可选:监听浏览器原生的网络变化事件,无需等待请求发起即可实时更新状态 window.addEventListener('online', () => this.setOnlineStatus(true)); window.addEventListener('offline', () => this.setOnlineStatus(false)); } }
- 第二步:修改HttpInterceptor,注入服务更新状态,同时修正原有逻辑问题
原拦截器中无网时直接return会返回undefined,导致上游订阅抛出类型错误,需要修改为返回错误Observable:
import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { NetworkStatusService } from './network-status.service'; // 替换为你实际的服务路径 @Injectable() export class ServiceInterceptor implements HttpInterceptor { constructor(private networkStatusService: NetworkStatusService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { req = req.clone({ setHeaders: { 'Content-Type': 'application/json', 'Accept': 'application/json' } }); // 更新当前网络状态 this.networkStatusService.setOnlineStatus(window.navigator.onLine); if (!window.navigator.onLine) { console.log("no internet connection"); // 抛出无网错误,上游请求订阅可直接捕获 return throwError(() => new Error('无网络连接')); } return next.handle(req); } }
- 第三步:在Home组件中订阅网络状态,控制自定义无网组件显示
import { Component, OnInit, OnDestroy } from '@angular/core'; import { DataService } from '../data.service'; import { NetworkStatusService } from '../network-status.service'; // 替换为你实际的服务路径 import { Subscription } from 'rxjs'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'] }) export class HomeComponent implements OnInit, OnDestroy { products = []; isOnline = true; private networkSub?: Subscription; constructor( private dataService: DataService, private networkStatusService: NetworkStatusService ) { } ngOnInit() { // 订阅网络状态变化 this.networkSub = this.networkStatusService.isOnline$.subscribe(status => { this.isOnline = status; }); this.dataService.sendGetRequest().subscribe({ next: (data: any) => { console.log(data); this.products = data; }, error: (err) => { console.log('请求出错:', err.message); } }); } ngOnDestroy() { // 取消订阅避免内存泄漏 this.networkSub?.unsubscribe(); } }
对应home.component.html 用法示例:
<!-- 无网时展示自定义离线组件 --> <app-your-offline-component *ngIf="!isOnline"></app-your-offline-component> <!-- 有网时展示正常业务内容 --> <div *ngIf="isOnline"> <div *ngFor="let product of products"> {{ product | json }} </div> </div>
内容的提问来源于stack exchange,提问作者depreston
相关产品推荐
相关产品推荐

