Network Connection Status at runtime using a Service Provider

I am trying to create a Provider that will look for network connection and I will inject it in all the views I need.

Came across this nice example on how to go about it. This particular example shows how to do it using views and I am trying to do it using a Provider class.

My problem is that I am not able to figure out how to return the Observable from this Provider. Sure it is my lack of knowledge about Observable/rxjs and few other things. Still learning new things in Ionic, Angular, TypeScript, rxJS, etc. every other day. :slight_smile:

I need to implement it quickly so would highly appreciate if somebody can please help me on how I should be implementing it or what I need to to do so that I can return an Observable from my Provider that I can subscribe to in all the views where I will be using it.

Following is my Provider code:

network-service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

import { Network } from '@ionic-native/network';

@Injectable()
export class NetworkService {
    private appOnline: boolean = true;

    constructor(private network: Network) {
        console.log('In NetworkService->constructor().');
    }

    isAppOnline(): boolean {
        return this.appOnline;
    }

    onConnect(): Observable<any> {
        this.network.onConnect().subscribe(data => {
            console.log(data);
            this.appOnline = true;
            return Observable.create(observer => {
                observer.next(data);
                observer.complete();
            });
        });

        //return this.network.onConnect(); <= If I just have this, it works but then I cannot set the 'appOnline' variable.
    }

    onDisconnect(): Observable<any> {
        this.network.onDisconnect().subscribe(data => {
            console.log(data);
            this.appOnline = false;
            return Observable.create(observer => {
                observer.next(data);
                observer.complete();
            });
        });
        
        //return this.network.onDisconnect(); <= If I just have this, it works but then I cannot set the 'appOnline' variable.
    }
}

When I do this, I get the following error on Observable<any> return type of onConnect() and onDisconnect() methods:

A function whose declared type is neither ‘void’ nor ‘any’ must return a value.

Following is my view class that uses the above NetworkService:

home-page.ts

// Here I imported the NetworkService provider and Subscription from rxJS along with other things I needed

@Component({
    selector: 'page-home',
    templateUrl: 'home.page.html'
})
export class HomePage {
   ...
   ...
    connected: Subscription;
    disconnected: Subscription;
   ...
   ...

    constructor(public navCtrl: NavController, public navParams: NavParams,
                private homeService: HomePageService, private platform: Platform, 
                private netService: NetworkService) {
      console.log('In HomePage->constructor');
    }

   ...
   ...
   ...

    ionViewDidEnter() {
        this.connected = this.netService.onConnect().subscribe(
            (data) => {
                // DO SOMETHING WHEN THE CONNECTION EXIST
            }, 
            (error) => {
                console.error('error is: ' + JSON.stringify(error));
            }
        );

        this.disconnected = this.netService.onDisconnect().subscribe(
            (data) => {
                // DO SOMETHING WHEN THE CONNECTION IS LOST
            }, 
            (error) => {
                console.error('error is: ' + JSON.stringify(error));
            }
        );
    }

    ionViewWillLeave(){
        this.connected.unsubscribe();
        this.disconnected.unsubscribe();
    }
}

Any help will be highly appreciated.

Thanks!

Several heuristics which will hopefully help you here:

  • never use any in your code
  • never explicitly instantiate Observables with create()
  • the first word you type in any method that calls a source that returns a future (Promise/Observable), such as onConnect(), must be return, unless said method is declared to return void and you don’t care when anything resolves

Thanks @rapropos for the quick reply, appreciated!

  • I am returning any becauseas per the documentation, the onConnect() and onDisconnect() methods in ionic-native/network->Network returns an Observable<any>. What should I be returning otherwise?

  • How else can I create and return an Observable? Tried Observable.of() but that also didn’t work.

  • Perhaps that’s the reason the commented line in onConnect() and onDisconnect() works. That is, if I only have return this.network.onConnect(); or return this.network.onDisconnect(); in those respective methods with no other code, it works fine. But if I do it that way then I don’t how to set my NetworkService’s appOnline flag. Any ideas?

Thanks.

Can you say in one sentence what functionality you want to implement? I don’t understand your post.

Hi @AaronSterling,

I would like to implement this using a Provider class in my Ionic app.

Thank you.

The code on that page looks kind of klugey. Are you really unable to say in your own words what you want to accomplish?

I would say Observable<void>, and argue that the ionic-native shim not returning that type is a bug. I may file a PR about this.

You don’t need to create it. You simply need to transform the one you are given via operators such as map() or mergeMap(). You could do something like this:

onConnect(): Observable<void> {
  return this.network.onConnect().map(() => {
    this.appOnline = true;
  });
}
1 Like

@AaronSterling

Okay, simply put and to generalize, I want to do the following:

  1. Write a Provider and implement a method that calls another third-party service which returns an Observable.
  2. Before returning from this method I want to set a variable in my Provider with the one of the values in the object that the third-party service’s returned Observable has.
  3. Return the Observable I got from this third-party service.

One above is done then I can use this Provider anywhere by subscribe() to its method.

Hope this is easy for you to understand.

Thanks.

private _variable: SomeType;

getExternalStream(): Observable<TypeOfStream> {
  return this.network.getStream().do(dataReceived => this._variable = dataReceived.propertyOfInterest);
}
1 Like

Aah ha!!! So I was on the right track!

Thanks a ton @rapropos !!! Very much appreciated!

This is what I had done and it worked just before you sent it:

    onConnect(): Observable<any> {
        return this.network.onConnect()
          .map((data) => {
            if(data.type === 'online') {
                NetworkService.appOnline = true;
            }
            else {
                NetworkService.appOnline = false;
            }

            return data;
          })
          .catch((error) => {
                console.error('In NetworkService->handleError(), ERROR is: ' + error);
                return Observable.throw(error);
          });    
    }   

I really appreciate your patience and the insights and fine points you give with your replies.