Nicolas Taboada
Nicolas Taboada

Reputation: 81

Understanding Node - Writing Asynchronous code

I am making my first steps on NodeJs. I came from Java world, and my head stuck when writing asynchronous code. I have read a lot about asynchronous flow, when dealing with I/O block operations but i don't really know how to solve this issue.

I am doing a google API call, when i create an instance of "point" object to retrieve longitude and latitude of the point.

In my "app.js" flow, i invoke a function that inside of it call another function that requires that longitude and latitude. As you see, at this point google API call didn't come back and its retrieve "undefined".

How to think this problem in a "Asynchronous way"?

//app.js

const express = require('express');
const POI = require('./models/poi');
var app = express ();

app.get('/', (req, res) => {

    var poiA = new POI(19146, "Saraza", 2, 3);
    var poiB = new POI(19146, "Saraza", 4, 5);


    console.log(poiA.estaAXMetrosDeOtroPoi(poiB, 10));

});

app.listen(3000);

const Point = require('./point');

function POI (direccion, nombre) {

    var self = this;

    var direction = direccion;

    var nombre = nombre;

    var point = new Point(direccion);


    self.getPoint = () => {
        return point;
    };

    self.estaAXMetrosDeOtroPoi = (otroPoi, distancia) => {
        let poiDistance = point.distanceBetweenPOIsCoords(point, otroPoi.getPoint());
        return (distancia >= poiDistance);
    };

}

module.exports = POI;

var geolib = require('geolib');
var geoCode = require('../services/geoCode');

function Point (direccion){

    var self = this;

    self.latitude;
    self.longitude;

    
    
    self.geoLocalizate =  (direccion) => {
        
        //Here i am making google API call
        
        geoCode.geocodeAddress(direccion, (errorMessage, results) => {
            if(errorMessage){
                self.latitude = null;
                self.longitude = null;
            }else{
                self.latitude = results.latitude;
                self.longitude = results.longitude;
            }
        });

    };

    self.geoLocalizate(direccion);

    self.getCoord = () => {
        return {"latitude": self.latitude, "longitude":                                         self.longitude};
    };
    
    //Function throwing error, becouse of latitude, longitude "Undefined"
    
    self.distanceBetweenPOIsCoords = (pointA, pointB) => {
        let coordA = pointA.getCoord();
        let coordB = pointB.getCoord();
        return geolib.getDistance(coordA, coordB);
    };


};

Upvotes: 0

Views: 233

Answers (1)

FluffyNights
FluffyNights

Reputation: 292

You should be aware that if you call an async function, you have no garantuee that it will finish at some point in your code. That means that

 self.geoLocalizate(direccion);
self.getCoord = () => {
        return {"latitude": self.latitude, "longitude":                                         self.longitude};
    };
...

will be processed before

geoCode.geocodeAddress(direccion, ...

has finished and thats why the values you define in your callback are undefined. The real execution might look like this, e.g.:

var self = this;

self.latitude;
self.longitude;



self.geoLocalizate =  (direccion) => {

    //Here you make the async call, but execution continues...

};

self.geoLocalizate(direccion);

self.getCoord = () => {
    return {"latitude": self.latitude, "longitude":                                         self.longitude}; // undefined, because async has not finished
};

// NOW, async function has finished, and your callback code is executed...
if(errorMessage){
            self.latitude = null;
            self.longitude = null;
        }else{
            self.latitude = results.latitude;
            self.longitude = results.longitude;
        }
//Function throwing error, becouse of latitude, longitude "Undefined"

self.distanceBetweenPOIsCoords = (pointA, pointB) => {
    let coordA = pointA.getCoord();
    let coordB = pointB.getCoord();
    return geolib.getDistance(coordA, coordB);
};

};

also, you cannot return something from an async function call, you have to provide a callback function and pass your return object to it. to garantuee proper execution, you have to wrap all code that required the async function to be completed in your callback, e.g. like this

function Point (direccion, callback){

var self = this;

self.latitude;
self.longitude;

self.geoLocalizate =  (direccion) => {

    //Here i am making google API call

    geoCode.geocodeAddress(direccion, (errorMessage, results) => {
        if(errorMessage){
            self.latitude = null;
            self.longitude = null;
        }else{
            self.latitude = results.latitude;
            self.longitude = results.longitude;
        }

    self.geoLocalizate(direccion);

    self.getCoord = () => {
        return callback(null, {"latitude": self.latitude, "longitude":                                         
        self.longitude});
    };

    self.distanceBetweenPOIsCoords = (pointA, pointB) => {
        let coordA = pointA.getCoord();
        let coordB = pointB.getCoord();
        return callback(null, geolib.getDistance(coordA, coordB));
   };
  });
};

Upvotes: 1

Related Questions