0

This may be a novice question but I am trying to create a function that returns true. However, this is based on what happens within several other functions inside.

function checkGeo(){

    // CHECK FOR GEOLOCATION
    if( "geolocation" in navigator ) {

        navigator.geolocation.getCurrentPosition( function(position){
            sessionStorage.pinlat = position.coords.latitude; 
            sessionStorage.pinlon = position.coords.longitude; 
            // position object is set!
        });

        // position is not defined
        if ( position.coords.latitude && position.coords.longitude ){ 
           return true; 
        }

    }

}

This is the order I want things to happen with my geolocation check but I'm a bit surprised that the nested if is tested before the getCurrentPosition method finishes.

Putting this condition within the getCurrentPosition success function and returning true from there does not make checkGeo return true. How do I check if this asyncronous function has ended and therefore check its results in order to return true?

Ben Racicot
  • 4,039
  • 8
  • 42
  • 96

3 Answers3

1

position in the anonymous function is not the same as position in the if statement after it. Scope in JavaScript (ignoring ES6 let keyword for simplicity) is by function.

Additionally, if getCurrentPosition() is asynchronous, then you can't rely on the anonymous callback function to run before anything else.

If all you want the return true to signify is that you are trying to get geolocation info without any guarantee that you will be successful, use something more like this:

function checkGeo(){
    var hasGeolocation = false;

    // CHECK FOR GEOLOCATION
    if( "geolocation" in navigator ) {
        hasGeolocation = true;

        navigator.geolocation.getCurrentPosition( function(position){
            sessionStorage.pinlat = position.coords.latitude; 
            sessionStorage.pinlon = position.coords.longitude; 
            // position object is set! but only inside this function.
        });

        return hasGeolocation;
    }
}

On the other hand, if you are trying to have return true indicate that the geolocation was successfully set, then you need to indicate it some other way than the return value of the synchronous function, because you won't know that it will be set (an error might occur, a user might disallow geolocation for your site etc.) until the asynchronous function invokes the callback.

Trott
  • 52,114
  • 21
  • 134
  • 179
  • I disagree. That does not define if I actually have location, correct? +1 for the scoping! *headdesk* – Ben Racicot Apr 25 '15 at 21:50
  • Correct, it does not tell you if you have the location, just that there is a means for trying to retrieve the location. I do indicate that in the text above the code. – Trott Apr 25 '15 at 21:55
  • Thanks for ur help. Maybe the question is more specifically: How to watch for `getCurrentPosition()` to end and check its values then return true if they meet conditions. – Ben Racicot Apr 25 '15 at 22:02
1

Have your function have a finished variable

function checkGeo(){
    var self = this;
    this.ready  = function () {}
    this.result = false;
    if("geolocation" in navigator) {
        navigator.geolocation.getCurrentPosition(function(position) {
            sessionStorage.pinlat = position.coords.latitude; 
            sessionStorage.pinlon = position.coords.longitude; 
            self.result = (position.coords.latitude && position.coords.longitude);
            self.ready.call(self);
        });
    }
}

Now you can use the function:

var run = new checkGeo();
run.ready = function () {
    alert(this.result); //Both work
    alert(run.result);  //Both work
};

A bit more complicated, but better programming in my opinion.

Downgoat
  • 11,422
  • 5
  • 37
  • 64
  • I don't get most of this, would you expound? It seems that `self` does not have a `ready` method. Only `this` does. Also, is `self.result` the "finished" var you speak of? – Ben Racicot Apr 25 '15 at 22:00
  • @BenRacicot JavaScript is a little weird. `self` is actually referring to checkGeo's `this`. Because `.getCurrentPosition` has a different scope, we need to use `self` so we can access this. `var self = this` doesn't actually create a copy of this, more like a reference. [Here's a question](http://stackoverflow.com/questions/337878/var-self-this) – Downgoat Apr 25 '15 at 22:08
  • Ok, I think I've got this. `run.ready` actually has the scope of `getCurrentPosition` which is how we can grab .result from it? – Ben Racicot Apr 25 '15 at 22:48
  • @BenRacicot Yeah, that's pretty much it – Downgoat Apr 25 '15 at 22:50
  • Dude, thank you. Nice code and explanation. I hope I can adapt this to future development. – Ben Racicot Apr 25 '15 at 22:51
0

The geolocation call is asynchronous, so you can't return the result from the function. When the function ends, you don't yet know the result from the asynchronous call. Returning anything from the callback for the asynchronous call won't make that the return value of the function, because the function has already returned.

You can use callback to report the result back. You have to use the code that checks the position in the callback for the asynchronous call:

function checkGeo(callback){
  if( "geolocation" in navigator ) {
    navigator.geolocation.getCurrentPosition(function(position){
      sessionStorage.pinlat = position.coords.latitude; 
      sessionStorage.pinlon = position.coords.longitude; 
      callback(position.coords.latitude && position.coords.longitude);
    });
  } else {
    callback(false);
  }
}

Usage:

checkGeo(function(exists){
  // here you can use the result
  if (exists) {
    // ...
  }
});
Guffa
  • 640,220
  • 96
  • 678
  • 956
  • *mind blown* so create your own callbacks to watch for success when waiting for async functions to finish? I do get a `callback is not a function` error? – Ben Racicot Apr 25 '15 at 22:12
  • @BenRacicot: Check the spelling, and that you have sent a function in the call. – Guffa Apr 25 '15 at 22:22
  • This actually makes sense, there is no function called `callback` of course its going to report an error. Can you explain how sending along a function would work without pseudo code? – Ben Racicot Apr 25 '15 at 22:28
  • @BenRacicot: You don't have to name the function `callback`, it's the name of the parameter in the `checkGeo` function. The code in the example isn't pseudo code, it's actual code that you can use. You just need to complete it with some code to use the result if you want something to happen after the call. – Guffa Apr 25 '15 at 22:36