【问题标题】:Angular ngOnDestroyAngular ngOnDestroy
【发布时间】:2021-01-09 04:55:47
【问题描述】:

我一直在尝试将网络插件设置为应用程序上的服务,以判断是否有互联网。

在我的示例中,我设置了两个组件:

  1. 直接在其中实现网络侦听器的 HOME 组件和
  2. 订阅 networkService 中的 BehaviourSubject 可观察对象的 TEST 组件

我的问题是当我从一个导航到另一个时试图破坏组件。加载应用程序的组件永远不会被破坏。即使我在 ngOnDestroy() 之上实现了类似 @HostListener('window:beforeunload') 的东西。

我已经在两个组件上实现了 ngOnDestroy 来分别移除监听器或取消订阅 networkServices 的 observable。

我注意到,如果我在首页上刷新应用:

  1. 我导航到 TEST 并且 HOME.ngOnDestroy() 没有被调用。
  2. 当我从 TEST 导航回 HOME 时,会调用 TEST.ngOnDestroy()。

如果我在 TEST 上刷新应用程序,会发生相同的行为但相反

  1. 我导航到 HOME 并且没有调用 TEST.ngOnDestroy()。
  2. 当我从 HOME 导航回 TEST 时,会调用 TEST.ngOnDestroy()。

我已将项目上传到公共 git 以防万一: https://github.com/jjgl/ionicNetworkCapacitorTests/

但这里是主要部分:

首页

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Plugins, NetworkStatus, PluginListenerHandle } from '@capacitor/core';

const { Network } = Plugins;

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit, OnDestroy {
  networkStatus: NetworkStatus;
  networkListenerHome: PluginListenerHandle;

  async ngOnInit() {
    this.networkListenerHome = Network.addListener('networkStatusChange', (status) => {
      console.log("Home Page Network status changed", status);
      this.networkStatus = status;
    });

    this.networkStatus = await Network.getStatus();
  }

  ngOnDestroy() {
    console.log('home destroyed')
    this.networkListenerHome.remove();
  }
}

测试

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { ConnectionStatus, NetworkService } from 'src/app/services/network.service';

@Component({
  selector: 'app-test-page',
  templateUrl: './test-page.page.html',
  styleUrls: ['./test-page.page.scss'],
})

export class TestPagePage implements OnInit, OnDestroy {
  subscription : Subscription
  private statusOnline : boolean;

  constructor(private networkService: NetworkService) {}

  async ngOnInit() {
    console.log('hola')
    this.subscription = this.networkService.onNetworkChange().subscribe((status: ConnectionStatus) => {
      this.statusOnline = status == ConnectionStatus.Online ? true : false;
      console.log('network change, status:', status);
    })
  }

  ngOnDestroy() { 
    console.log('test destroyed')
    this.subscription.unsubscribe()
  }

}

网络服务

import { Injectable, OnDestroy } from '@angular/core';
import { Plugins, NetworkStatus, PluginListenerHandle } from '@capacitor/core';
import { BehaviorSubject, Observable } from 'rxjs';

const { Network } = Plugins;

export enum ConnectionStatus {
  Online,
  Offline
}

@Injectable({
  providedIn: 'root'
})

export class NetworkService implements OnDestroy {

  private netStatus: BehaviorSubject<ConnectionStatus> = new BehaviorSubject(ConnectionStatus.Offline);
  networkStatus: NetworkStatus;
  networkListener: PluginListenerHandle;

  constructor() { 
    this.networkListener = Network.addListener('networkStatusChange', (status) => {
      console.log("Service Network status changed", status);
      this.networkStatus = status;
      let auxStatus = status && status.connected ? ConnectionStatus.Online : ConnectionStatus.Offline;
      this.netStatus.next(auxStatus)
    });
    this.initialState()
  }
  

  private async initialState(){
    this.networkStatus = await Network.getStatus();
    let auxStatus = this.networkStatus && this.networkStatus.connected ? ConnectionStatus.Online : ConnectionStatus.Offline;
    this.netStatus.next(auxStatus)
  }
  public onNetworkChange(): Observable<ConnectionStatus> {
    return this.netStatus.asObservable();
  }
 
  public getCurrentNetworkStatus(): ConnectionStatus {
    return this.netStatus.getValue();
  }

  ngOnDestroy(): void {
    console.log('services destroyed')
    this.networkListener.remove();
  }


}

不用说我是 Angular 的新手,所以也可以随意指出其他事情,欢迎所有 cmets。

PS:我已经在 networkService 上实现了 ngOnDestroy,但我没有从 TEST 调用它,因为在 TEST.ngOnDestroy 第一次被调用后导航回 TEST 时服务不会重新实例化。

【问题讨论】:

    标签: angular ionic-framework capacitor ngondestroy


    【解决方案1】:

    您不能在服务中使用 Angular 生命周期。仅在组件内部使用。

    请在 app.component.ts 中调用Network.addListener

    ...
    export class AppComponent implements OnInit {
      subscription : Subscription
      private statusOnline : boolean;
    
      constructor(private networkService: NetworkService) {}
    
      async ngOnInit() {
        this.networkListener = Network.addListener('networkStatusChange', (status) => {
          console.log("Service Network status changed", status);
          this.networkStatus = status;
          let auxStatus = status && status.connected ? ConnectionStatus.Online : ConnectionStatus.Offline;
          this.networkService.netStatus.next(auxStatus) // Push the new status to NetworkService behaviorSubject
        });
      }
    }
    

    app.component.ts 是一个根单例组件,因此在您刷新浏览器选项卡之前,它既不会被破坏也不会被刷新。现在您可以在任何组件中使用 NetworkService 中的 netstatus,就像您已经在做的那样。

    ...
    export class NetworkService {
    
      private netStatus: BehaviorSubject<ConnectionStatus> = new BehaviorSubject(ConnectionStatus.Offline);
    
      public onNetworkChange(): Observable<ConnectionStatus> {
        return this.netStatus.asObservable();
      }
     
      public getCurrentNetworkStatus(): ConnectionStatus {
        return this.netStatus.getValue();
      }
    }
    

    【讨论】:

    • 您好 Polyglot,感谢您的评论。我喜欢你提出的建议,我让它运行起来了,一切都很棒!你知道为什么即使我在 ngOnDestroy() 之上实现 @HostListener('window:beforeunload') 之类的东西,加载的第一个组件也不会被销毁?这是我的主要问题。
    • 我认为这是因为您使用的是 &lt;ion-router-outlet&gt; 而不是 Angular &lt;router-outlet&gt;。相反,您可以使用 ionic-router-outlet 挂钩。 ionViewDidLeave 将完成您需要的工作。如果我的代码有效,您能否将答案标记为已接受?
    • 离子挂钩,做到了!了解角度结束和离子开始的地方很有趣。谢谢 Polyglot,已接受您的回答!
    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 2018-12-18
    • 2018-12-12
    • 2018-02-04
    • 1970-01-01
    • 2018-05-27
    • 2020-04-02
    • 2021-12-12
    相关资源
    最近更新 更多