[SalesForce] Problem calling apex method imperatively LWC

i'm trying to call a back-end apex method imperatively which returns the weather information for the logged in user's location and it throws the following error in console :

error : Error: newValue cannot be undefined. Observable name: MapWithFilterOnSubscribeBehaviorSubject <= DistinctUntilChanged <= RootObservable: lds.Apex::WeatherData:getWeatherData:false:{"sLatitude":"","sLongitude":""}, newValue: undefined

Below is the js code:

 import { LightningElement , track} from 'lwc';
import WEATHER_DATA from '@salesforce/apex/WeatherData.getWeatherData';
export default class UserLocation extends LightningElement {
    @track sLatitude;
    @track sLongitude;
    connectedCallback(){
        let sLatitude = '';
        let sLongitude = '';
        if(navigator.geolocation){
            navigator.geolocation.getCurrentPosition(function(position) {
                sLatitude = position.coords.latitude;
                /* eslint-disable no-console */
                console.log('position  latitude : ' ,sLatitude);
                sLongitude = position.coords.longitude;
                /* eslint-disable no-console */
                console.log('position  longitude : ' ,sLongitude);
              });
        }else{
            /* eslint-disable no-console */
            console.log('inside else');
        }
        /* eslint-disable no-console */
        console.log('position  latitude 11: ' ,sLatitude);
        if((sLatitude !== undefined && sLatitude !== '') && (sLongitude !== undefined && sLongitude !== '')){
            /* eslint-disable no-console */
            console.log('Will call backend from here  ');
            WEATHER_DATA({sLatitude : sLatitude , sLongitude: sLongitude})
                .then(result=>{
                    /*eslint-disable no-console*/
                    console.log('RESULT : ',result);
                })
                .catch(error=>{
                    /*eslint-disable no-console*/
                    console.log('error : ',error);
                })
        }else{
            //Do something here 
        }
    }
}

It gives the following console messages :

enter image description here

What's weird here is the order in which the console messages are printed. This seems to be violating the order of execution somehow and I'm not sure why it's happening.

Regarding the back-end code, it's working fine as I have already tested it by passing the latitude and longitude values through anonymous window.

Can someone help me understand and solve this.

Best Answer

I believe you need to slightly redesign this to behave as you're expecting it to. The way I'm reading this, your back-end call will never fire because your geolocation variables will not be set by the time it gets there. Here's a quick example:

connectedCallback(){

    this.getLocation().then(res => {
        // process coordinates/perform back-end call here
    })

}

getLocation(){
    return new Promise((resolve, reject) => {
        navigator.geolocation.getCurrentPosition(position => {
            resolve(position);
        });
    })
}

This pattern will ensure the getCurrentPosition callback is executed before you perform your back-end call. This function is asynchronous so you need to handle it accordingly.