Search code examples
javascriptangulartypescriptgeolocationangular5

Angular 5 too many geolocation position responses


I want to write in Angular 5 component, function that geting me every 3 seconds my current location if it was changed.

My code looks like that:

export class WorkComponent implements OnInit {

 constructor(private userService: UserService) {}

 ngOnInit() {
    this.subscribeCurrentPosition();
  }

  subscribeCurrentPosition() {
    if (window.navigator.geolocation) {
      window.navigator.geolocation.watchPosition(
        (position) => {
          this.myLocation = new TrackLocation(null, position.coords.latitude, position.coords.longitude);
          this.userService.sendCurrentPosition(this.myLocation, this.supplierId);  //send position to backend
          setInterval(() => this.subscribeCurrentPosition(), 3000);
        }, (error) => {
          LoggingService.error('Geolocation error: '+ error);
        });
      } else {
        LoggingService.error('Geolocation not supported in this browser');
      }
  }
}

I received location change in function subscribeCurrentPosition(), but problem is that every 3 seconds function is called more and more times 1, 2, 4.. It seems like every function call, calling 2 times next function. And then I received alert that I send too many requests from geolocation api.

I don't know why function subscribeCurrentPosition() is calling more than one time every 3 seconds. There is only one instance of component in time.


Solution

  • This is because you are using setInterval. Every time you use setInterval, you are creating a new task that will repeat indefinitely. And you are recursively calling sentInterval every time your function executes. That's why you are seeing these tasks multiply as time goes on. Use setTimeout instead. It will only execute once. And since you are using a recursive mechanism, it will continue to get called every time you receive a response:

      subscribeCurrentPosition() {
        if (window.navigator.geolocation) {
          window.navigator.geolocation.watchPosition(
            (position) => {
              this.myLocation = new TrackLocation(null, position.coords.latitude, position.coords.longitude);
              this.userService.sendCurrentPosition(this.myLocation, this.supplierId);  //send position to backend
              setTimeout(() => this.subscribeCurrentPosition(), 3000);
            }, (error) => {
              LoggingService.error('Geolocation error: '+ error);
            });
          } else {
            LoggingService.error('Geolocation not supported in this browser');
          }
      }
    

    Or, you can use setInterval, but do it outside your function:

      subscribeCurrentPosition() {
        if (window.navigator.geolocation) {
          window.navigator.geolocation.watchPosition(
            (position) => {
              this.myLocation = new TrackLocation(null, position.coords.latitude, position.coords.longitude);
              this.userService.sendCurrentPosition(this.myLocation, this.supplierId);  //send position to backend
            }, (error) => {
              LoggingService.error('Geolocation error: '+ error);
            });
          } else {
            LoggingService.error('Geolocation not supported in this browser');
          }
      }
      setInterval(() => this.subscribeCurrentPosition(), 3000);