Juarrow
Juarrow

Reputation: 2384

Cannot read property of undefined when subscribing to location updates and pushing to BehaviorSubject

As i want to use location information in my Ionic 5/Capacitor app, i wrote a first version of a wrapper around the Geolocation API.

The issue is, that when i inject this service and call startReceivingLocationUpdates() i get the following error:

core.js:6014 ERROR TypeError: Cannot read property 'locationSubject' of undefined
    at locationCallback (location.service.ts:51)
    at window.navigator.geolocation.watchPosition.Object.enableHighAccuracy (geolocation.js:30)
    at ZoneDelegate.invoke (zone-evergreen.js:359)
    at Object.onInvoke (core.js:39699)
    at ZoneDelegate.invoke (zone-evergreen.js:358)
    at Zone.runGuarded (zone-evergreen.js:134)
    at zone-evergreen.js:118

My location service


    import { Injectable } from '@angular/core';
    import { Geolocation, GeolocationOptions, GeolocationPosition } from '@capacitor/core';
    import { BehaviorSubject, Observable } from 'rxjs';

    const locationOptions: GeolocationOptions = {
      enableHighAccuracy: true,
      requireAltitude: false
    };

    @Injectable({
      providedIn: 'root'
    })
    export class LocationService {

      private locationSubject = new BehaviorSubject<GeolocationPosition>(null);

      private watchId: string = null;

      constructor() {
      }

      receivingLocationUpdates(): boolean {
        return this.watchId != null;
      }

      startReceivingLocationUpdates()
      {
        if(this.watchId !== null)
          return;

        this.watchId = Geolocation.watchPosition(locationOptions, this.locationCallback);
      }

      stopReceivingLocationUpdates()
      {
        if(this.watchId === null)
          return;

        Geolocation.clearWatch({id: this.watchId })
          .then(_ => {
            this.watchId = null;
          });
      }

      subscribe(): Observable<GeolocationPosition>
      {
        return this.locationSubject.asObservable();
      }

      private locationCallback(location: GeolocationPosition) {
        this.locationSubject.next(location);
      }
    }

What am i doing wrong?

Upvotes: 0

Views: 532

Answers (1)

Sergey Rudenko
Sergey Rudenko

Reputation: 9225

The issue here is likely that you are losing what 'this' is pointing at, since the callback function (locationCallBack) gets executed within different scope than your class.

To fix this you should either bind the execution scope or make this transparent.

Try using fat arrow function:

  private locationCallback = (location: GeolocationPosition) => {
    this.locationSubject.next(location);
  }

Alternatively you can:

  • pass your class's 'this' scope
  • bind 'this' using .bind(this) approach

Upvotes: 3

Related Questions