Jeffrey Sun
Jeffrey Sun

Reputation: 121

How to change the subscription of an Observable in response to user action?

I am adding geolocation to my app, and I need to start the observable Geolocation.watchPostion() some time before the user actually requests the location.

I had the idea to create instance variables

private locationObserver = (stub observer);
private locationSubscription;

and do

this.locationSubscription = Geolocation.watchPosition().subscribe(
  next => this.locationObserver.next(next),
  err  => this.locationObserver.error(error),
  comp => this.locationObserver.complete(complete)
)

And then at some later point call the following.

onRequestLocation(){
  this.locationObserver = Observer.create(
    location => {
      this.doMyStuff(location);
      this.locationSubscription.unsubscribe();
    }
  )
}

However, this doesn't feel like the right way to do this. Is this bad?

My goal is to start Geolocation.watchPosition(), and then, in response to a user event, start doing something. I would also like a timeout event to occur 5 seconds after the user event.

Here is another possibility that still doesn't feel right:

I make instance variables

private userEventHasOccured
private locationSubscription

and do

this.locationSubscription = Geolocation.watchPosition().subscribe(
  next => {
    if (userEventHasOccured) {
      this.doMyStuff(next);
      this.unsubscribeLocation();
    }
  }
)

public unsubscribeLocation() {
  this.locationSubscription.unsubscribe();
}

and

onUserEvent(){
  this.userEventHasOccured = true;
}

Also, is there a less annoying way of having a subscription end itself?

Upvotes: 0

Views: 474

Answers (1)

Jeffrey Sun
Jeffrey Sun

Reputation: 121

My problem was a lack of understanding. Of course an observable can have more than one subscription.

Edit: Sorry! Some more explanation.

In the end, my working solution was to declare instance variables

this.stubSubscription
this.actualSubscription

and then call the following on page load, user action, and page leave, respectively.

ionViewDidEnter() {
  this.stubSubscription = Geolocation.watchPosition()
    .subscribe(() => {}, () => {});

onUserAction() {
  this.actualSubscription = Geolocation.watchPosition()
    .first(position => position.coords.accuracy <= 50) // 1st accurate-enough result
    .subscribe(position => this.doMyStuff(position))

ionViewWillLeave() {
  this.stubSubscription.unsubscribe();
  this.actualSubscription.unsubscribe();
}

ionic appears to be very good about actually calling willeavewhenever the user leaves. if not called, then geolocation just keeps running until the app is closed, which is bad. I would like to do this in a more reactive, as opposed to imperative, way...

Edit 2: I'm sure this is still not the best way to do this -- if you have any suggestions, please let me know!

Upvotes: 1

Related Questions