IONIC 2 native Network.onDisconnect() 运行代码两次

Posted

技术标签:

【中文标题】IONIC 2 native Network.onDisconnect() 运行代码两次【英文标题】:IONIC 2 native Network.onDisconnect() running code twice 【发布时间】:2017-07-13 20:20:21 【问题描述】:

我正在使用 ionic 2 RC1 并使用 sublime 作为文本编辑器。我需要检查网络连接是否连接。所以为此我使用离子原生Network。但我面临Network.onDisconnect() Observable 的问题。我编辑了initializeApp() 方法,在该方法中我检查网络连接并在连接断开时显示警报。我有以下代码写在app.component.ts

  showAlert(title, msg) 
    let alert = this.alertCtrl.create(
      title: title,
      subTitle: msg,
      buttons: ['OK']
    );
    alert.present();
  

  initializeApp() 
    this.platform.ready().then(() => 
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      let disconnectSubscription = Network.onDisconnect().subscribe(() => 
        this.showAlert("Error", "No internet connection");
      );
      StatusBar.styleDefault();
    );
  

我面临的问题是,如果应用程序与 Internet 断开连接,则会显示两次警报。我在post 中发现了类似的问题,但没有得到答复。在这方面的任何帮助将不胜感激。 提前致谢!

【问题讨论】:

你能解决这个问题吗? 不,我没有尝试解决它,因为我已被转移到其他基于 Web 的项目。我认为这个问题现在应该在框架的新版本中得到解决。 【参考方案1】:
this.network.onDisconnect().subscribe(() => 
    if(this.status == true)
      console.log("no need to call again")
      alert("no need to call again")
    
    else
      this.status = true;
      console.log(this.status)
      console.log('network was disconnected :-(');
      // alert('network was disconnected :-(');
      // this.prompt.ShowAlert('Connection Problem','Please check your internet connection and try again.')

      let modal = this.modalCtrl.create('NoInternetPage');
      modal.present();

      modal.onDidDismiss((info) => 
        console.log("on modal dismiss")
      );
    



  );

  this.network.onConnect().subscribe(() => 
    this.status = false;
  )

你可以试试这个简单的技巧

【讨论】:

请解释这如何解决 OP 的问题。有什么诀窍。 请看上面代码中的“this.status” if else 逻辑【参考方案2】:

您真正的问题是,您没有在实际类中使用绑定构造函数!如果您想在 app.component.ts 中调用它,那么只需将参数添加到您的

constructor(public network: Network)

并且直接在网络之外使用!所以叫:this.network.... 那么最好的方法是使用静态变量来控制它:

static checkedState: boolean = false;

在您编写完 OnConnect 语句后,将 checkedState 设置为 true 并使用 if 语句同时在 OnDisconnect 和 OnConnect 上捕获它,您应该只收到一次消息。顺便说一句:我在 eventsCtrl 中也有这种行为,我不知道 Ionic 是否可以更好地使用其他控制机制来处理这些事情。

问候 钢筋

【讨论】:

【参考方案3】:

我认为你应该使用下面的代码来避免这个问题。

import  Network  from 'ionic-native';

    @Injectable()
    export class NetworkService 
    previousStatus:any
        constructor() 

               

    showAlert(title, msg) 
        let alert = this.alertCtrl.create(
          title: title,
          subTitle: msg,
          buttons: ['OK']
        );
        alert.present();
              
          this.initializeApp();
          this.network.onDisconnect().subscribe( () => 
                if (this.previousStatus === Online) 
                    this.showAlert("Error", "No internet connection");
                
                this.previousStatus = Offline;
            );
            Network.onConnect().subscribe(() => 
                if (this.previousStatus === Offline) 
                 this.showAlert("Alert", "Network was connected");
                
                this.previousStatus = Online;
            );
        
    

【讨论】:

【参考方案4】:

我已经解决了这个问题。人们遇到的真正问题是,在很多情况下会创建多个 Ionic 页面实例。所以如果你在一个页面上注册了一个事件接收器,然后开始在 App 中来回导航,这个事件接收器会被注册多次。 解决方案是在 app.component.ts 的 intializeApp 方法中添加事件接收器,如下所示:

// top of page 
import  Observable  from 'rxjs/Observable';

initializeApp() 
    this.platform.ready().then(() => 
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      this.statusBar.styleDefault();
      this.splashScreen.hide();

      var offline = Observable.fromEvent(window, "offline");
      var online = Observable.fromEvent(window, "online");

      offline.subscribe(() =>           
          console.log('Offline event was detected.');
      );

      online.subscribe(() => 
          console.log('Online event was detected.');        
      )
    );
  

无论您在 App 中导航多少次,这两条日志消息都只会在您分别在线/离线时触发一次。

【讨论】:

所以如果你在一个页面上注册了一个事件接收器,然后开始在 App 中来回导航,那么这个事件接收器会被注册多次 '不要在离开页面时取消订阅事件(这是错误的,但它与插件无关)。建议在 app.component.ts 文件或共享服务中处理此问题,但如果您在应用程序的任何页面中正确执行操作,它应该可以正常工作。 这只能在浏览器中使用,不能在真实设备中使用!【参考方案5】:

为了避免这种情况,您可以过滤事件,并在状态从在线变为离线或从离线变为在线时执行某些操作(而不是每次触发事件时)由插件)。所以基本上你可以像这样创建一个服务来处理所有这些逻辑:

import  Injectable  from '@angular/core';
import  Network  from 'ionic-native';
import  Events  from 'ionic-angular';

export enum ConnectionStatusEnum 
    Online,
    Offline


@Injectable()
export class NetworkService 

    private previousStatus;

    constructor(private eventCtrl: Events) 
        this.previousStatus = ConnectionStatusEnum.Online;
    

    public initializeNetworkEvents(): void 
        Network.onDisconnect().subscribe(() => 
            if (this.previousStatus === ConnectionStatusEnum.Online) 
                this.eventCtrl.publish('network:offline');
            
            this.previousStatus = ConnectionStatusEnum.Offline;
        );
        Network.onConnect().subscribe(() => 
            if (this.previousStatus === ConnectionStatusEnum.Offline) 
                this.eventCtrl.publish('network:online');
            
            this.previousStatus = ConnectionStatusEnum.Online;
        );
    

所以我们的自定义事件(network:offlinenetwork:online)只会在连接真正改变时触发(修复了当连接状态完全没有改变时插件触发多个在线或离线事件的场景)。

然后,在您的app.component 文件中,您只需订阅我们的自定义事件:

// Offline event
this.eventCtrl.subscribe('network:offline', () => 
  // ...            
);

// Online event
this.eventCtrl.subscribe('network:online', () => 
  // ...            
);

【讨论】:

这对我来说仍然会触发两次 在许多在线帖子中提供了许多此类解决方案作为此问题的答案。这绝对是最优雅的答案。但是,它不会像其他解决方案一样不起作用(我已经尝试过)。该事件似乎同时触发多次或触发速度比上述代码执行和过滤网络的多余事件的速度更快。 嗯...我在一些应用程序中使用了上面的代码,但从未遇到过这个问题。如果只有一个 NetworkService 实例,即使插件事件触发得非常快,它也应该由服务逻辑 @JurgenW 处理。 我没有尝试你的代码。这确实取决于在离线或在线时有单个实例运行代码,请参阅我的答案。

以上是关于IONIC 2 native Network.onDisconnect() 运行代码两次的主要内容,如果未能解决你的问题,请参考以下文章

Ionic 2 - Google Maps Native:标记点击事件未触发

Ionic 2 Native Audio Android上没有声音

IONIC 2 native Network.onDisconnect() 运行代码两次

ionic-native/http 发出错误“NullInjectorError: No provider for HTTP!”

Ionic2使用第三方cordova插件(非Ionic2官方支持的native cordova插件)

ionic-native-transitions调用原生页面切换实现ionic路由切换