Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Having a senior moment - variable scope (I think!)

ANSWERED

Hi All,

 

I am very new to class programming, so am probably doing something really stupid. I have started to move my project into Ionic Views by @gaperton which will work very well for my app.

 

Anyway, the problem is the following line of code never calls my class method:

watchID = geolocation.watchPosition(()=>this.gpsbeat,()=>this.gpsError);

 

Yet the following line of code calls the method, but loses scope to my variables:

watchID = geolocation.watchPosition(this.gpsbeat,this.gpsError);

Any help / pointers would be greatly appreciated. Thank you.

 

For reference, the rest of the runMaster.class.js file is below for a little more context:

import { HeartRateSensor } from "heart-rate";
import { geolocation } from "geolocation";

class runMaster {
  
  readingNumber=0;
  lat=0;
  lon=0;
  speed=0;
  altitude=0;
  sensorReadTimer=0;
  hrmread=0;
  hrm=0;
  gps=0;

  start() {
    this.sensorReadTimer=setInterval(() => this.reading(),2000);
    this.hrm=new HeartRateSensor();
    this.hrm.onreading = () => this.hrmbeat();
    watchID = geolocation.watchPosition(()=>this.gpsbeat,()=>this.gpsError);
    this.hrm.start();
  }
  
  hrmbeat() {
    this.hrmread=this.hrm.heartRate;
  }

  gpsbeat(position) {
    this.lat=position.coords.latitude;
    this.lon=position.coords.longitude;
    this.speed=position.coords.speed;
    this.altitude=position.coords.altitude;
    this.readingNumber++;
    console.log(this.lat+"::"+this.lon+"::"+this.speed+"::"+this.altitude);
  }
  gpsError() {
    console.log("GPS Error");
  }

  reading() {
    console.log("HR="+this.hrmread+" lat="+this.lat+" lon="+this.lon+" speed="+this.speed+" altitude="+this.altitude+" Reading #"+this.readingNumber);
  }

  returnval() {
    return this.hrmread;
  }
  
  
  stop() {
    clearInterval(this.sensorReadTimer);
    console.log("Stop");
  }
}
export default new runMaster();

 

 

 

 

 

 

 

 

Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

There's another way of fixing this problem.

In the class definition, write:

 gpsbeat = position => {
    this.lat=position.coords.latitude;
    this.lon=position.coords.longitude;
    this.speed=position.coords.speed;
    this.altitude=position.coords.altitude;
    this.readingNumber++;
    console.log(this.lat+"::"+this.lon+"::"+this.speed+"::"+this.altitude);
  }
  gpsError = () => {
    console.log("GPS Error");
  }

 It will pin down "this" to your methods, so they can be safely used as callbacks. Like this:

watchID = geolocation.watchPosition(this.gpsbeat,this.gpsError);

I actually prefer this way. Looks a bit nicer. But it's generally the matter of taste.

View best answer in original post

Best Answer
6 REPLIES 6

I'm sure it's a scope thing to do with 'this' in anonymous arrow functions

 

Early versions of JS got around this with something like 

 

let that = this;  // class scope

watchID = geolocation.watchPosition(()=>that.gpsbeat,()=>that.gpsError);  

 

Best Answer
0 Votes

There's another way of fixing this problem.

In the class definition, write:

 gpsbeat = position => {
    this.lat=position.coords.latitude;
    this.lon=position.coords.longitude;
    this.speed=position.coords.speed;
    this.altitude=position.coords.altitude;
    this.readingNumber++;
    console.log(this.lat+"::"+this.lon+"::"+this.speed+"::"+this.altitude);
  }
  gpsError = () => {
    console.log("GPS Error");
  }

 It will pin down "this" to your methods, so they can be safely used as callbacks. Like this:

watchID = geolocation.watchPosition(this.gpsbeat,this.gpsError);

I actually prefer this way. Looks a bit nicer. But it's generally the matter of taste.

Best Answer

Thank you for the response @TechnoBuddhist - really appreciated.

 

I am sorry to report that doesn't seem to help 😞

Best Answer
0 Votes

@SunsetRunner

And in fact, you originally did it almost right. Just forgot to call your functions from within your arrow functions, which was a valid no-op JS expression. It should be:

 

watchID = geolocation.watchPosition(()=>this.gpsbeat(),()=>this.gpsError());

 
The difference between function( x ){ return ... } and x => ... is that the last one capture "this". So, you don't need to work it around with "var _this" or something. The keyword is "JS arrow functions".

Best Answer

Thank you @gaperton. I obviously need to go and read more about classes .....

 

I am digging deep getting to grips with your Ionic Views, but it really will be worth it. I know the app I want and need, and your class will help.

 

Again, thank you.

Best Answer
0 Votes

@gaperton Durrgh! yeah I remember reading this now - JS arrow function handles 'this'. That'll teach me to read as I go to sleep.

 

Obviously also missing the parenthesis off the call!

 

()=>this.gpsbeat(),()=>this.gpsError()

 Lessons learnt! Cheers!

Best Answer