首页 > 解决方案 > 如何解决 Ionic 中的区域感知承诺

问题描述

我正在使用带有电容器版本 2.2.0 的 ionic5。我正在使用电容器网络来检测网络是在线还是离线。但是 Network.getStatus() 返回“区域感知承诺”。以下是我尝试过的代码。

网络服务

import { Injectable, OnDestroy } from '@angular/core';
//import { Network } from '@ionic-native/network/ngx';
import { ErrorNotificationService } from '../service/error-notification.service';
import { errorMessages } from '../service/dao/errorMessageConstants';
import { TranslateConfigService } from './translate-config.service';
import { Plugins,NetworkStatus, PluginListenerHandle } from '@capacitor/core';
const { Network } = Plugins;
@Injectable({
  providedIn: 'root'
})
export class NetworkService  {
  networkStatus: NetworkStatus;
  networkListener: PluginListenerHandle;

  constructor(private errorService:ErrorNotificationService) {
    this.listenToInternet();
  }
  

  listenToInternet(){
    this.networkListener = Network.addListener('networkStatusChange', (status) => {
      console.log("Network status changed", status);
      if(status && !status.connected){
        this.errorService.showTextErrorAlert(this.translateService.getTranslatedValue("messages.no_connection"))
      }
      this.networkStatus = status;
   });
  }

   checkNetworkPresent(){
    return Network.getStatus().then(network =>{
      console.log(network,"network as service")
     return network;
    })
  }
}

由于电容器插件返回承诺,我正在使用“then”,它在我获得网络状态后执行。我在下面的拦截器中调用此方法,但我得到“区域感知承诺”。

Http 拦截器

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpInterceptor, HttpErrorResponse } from '@angular/common/http';
import { NetworkService } from './network.service'
import { NEVER, throwError } from 'rxjs';
import { LoaderService } from './loader.service'
import { ErrorNotificationService } from '../service/error-notification.service'

@Injectable({
  providedIn: 'root'
})
export class HttpInterceptorsService implements HttpInterceptor {
  networkStatus : any;
  constructor(private networkService:NetworkService,private loader:LoaderService,private errorService:ErrorNotificationService) {}
  intercept(req: HttpRequest<any>, next: HttpHandler) {
   
//here checknetworkPresent returns zone aware promise

    this.networkStatus = this.networkService.checkNetworkPresent();
    console.log(this.networkStatus,"Network")
    if(!this.networkStatus["connected"]){
     this.loader.hideLoader();
    // this.errorService.showTextErrorAlert("No Internet Connection")
     return throwError("no_connection");
    }else{
     return next.handle(req);
    }
  }
}

我在某个地方出错了吗?

标签: angular9capacitorionic5

解决方案


当我们要求 Angular 执行一些“Angular Zone”之外的事件/任务时,就会产生区域感知问题,所有这些都是为了确保我们可以完全控制应用程序。

NgZone 本身就是一个非常复杂的东西,一开始就很难理解。我建议你看看这个。您可以在 Javascript 中创建自己的区域。

回到你的问题。

所以目前这里发生的是对 networkStatus 插件的调用被阻止,因为它是在 NgZone 之外执行的。

为了解决您的问题,您需要:

  1. 在您的 NetworkService 中注入 ngZone。
  2. 根据您的用例包装您的代码run()或方法。runTask()

所以你需要做这样的事情:

@Injectable({
  providedIn: 'root'
})
export class NetworkService  {
  networkStatus: NetworkStatus;
  networkListener: PluginListenerHandle;

  constructor(
    private errorService:ErrorNotificationService,
    private ngZone: NgZone       // <~ 1. Inject ngZone 
   ) {
    this.listenToInternet();
  }
  

  listenToInternet(){
    this.networkListener = Network.addListener('networkStatusChange', (status) => {
      console.log("Network status changed", status);
      if(status && !status.connected){
        this.errorService.showTextErrorAlert(this.translateService.getTranslatedValue("messages.no_connection"))
      }
      this.networkStatus = status;
   });
  }

   checkNetworkPresent(){
    // 2. Wrap your code with `run` or `runTask` depending on your usecase
    this.ngZone.runTask(() => {
      return Network.getStatus().then(network =>{
      console.log(network,"network as service")
      return network;
    });
   });
  }
}

我希望这可以帮助你。

快乐编码。


推荐阅读