-1

I have a function for geocoding an address that returns the name of the city of the same address

  // geocode the given address
  geocodeAddress(address, callback) {
    this.mapsAPILoader.load().then(() => {
      var geocoder = new google.maps.Geocoder();
      geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          results[0].address_components.forEach(arrAddress => {
            if (arrAddress.types[0] == "locality") {
              callback(arrAddress.long_name);
            }
          })
        } else {
          console.log("Geocode was not successful for the following reason: " + status);
        }
      });
    });
  };

when I call that function and want to print the city name it is printed 'undefined' from the code line below the geocodeAddress function and after that is printed properly city name

this.geocodeAddress(this.offerAddress, data => {
  this.hostCity = data;
  console.log(this.hostCity);
});
console.log(this.hostCity);

I was trying to add some timeout before second console.log function but without any success

therefore, I'm interested how to access this value after returning data from geocoder because I need to use this data for storing in database and if I try to store like this

    this.geocodeAddress(this.offerAddress, data => {
            this.hostCity = data;
            this.service.addData({"address": this.offerAddress, "city": this.hostCity}, "/data")
                .subscribe(data => {
                  this.router.navigate(['list']);
                })
          });

it store data but router.navigate not working properly

so I need solution for accessing hostCity outside of geocodeAddress callback function, or how to properly call some another function inside this geocodeAddress callback function

Ante Ereš
  • 623
  • 4
  • 8
  • 24
  • 1
    What do you mean by this: "router.navigate not working properly"? – Daniel W Strimpel May 02 '18 at 14:09
  • it navigate url to list, but template view is not list template, it's still adding form template. And i tried call another function for opening error dialog "this..confirmDialog(ErrorDialog, "Something wrong");". It opens dialog but without message, and if i call this functions outside geocodeAddress callback function, everything works properly – Ante Ereš May 02 '18 at 14:12
  • In addition to processing the data inside of the `geocodeAddress` callback, change `function (results, status) { ... }` for `(results, status) => { ... }` to preserve the value of `this` with an arrow function. – ConnorsFan May 02 '18 at 14:32

1 Answers1

1

If you're using TypeScript, you can make your geocodeAddress method return a Promise, instead of using callbacks, and then use async/await:

async geocodeAddress(address): Promise<string[]> {
    return new Promise((resolve, reject) => {
        this.mapsAPILoader.load().then(() => {
           var geocoder = new google.maps.Geocoder();
           geocoder.geocode({ 'address': address }, function (results, status) {
               if (status == google.maps.GeocoderStatus.OK) {
                   const result: string[] = [];
                   results[0].address_components.forEach(arrAddress => {
                       if (arrAddress.types[0] == "locality") {
                           result.push(arrAddress.long_name);
                       }
                   });
                   resolve(results);
               } else {
                   console.log("Geocode was not successful for the following reason: " + status);
                   reject(status);
               }
           });
       });
    });
};

Now, this function returns an array with the long names of all the addresses you were seeking. To use it:

const data: string[] = await this.geocodeAddress(this.offerAddress);
this.hostCity = data[0];
// do whatever you want now

This way you get the benefits of asynchronous programming, with the simplicity of synchronous one.

Oscar Paz
  • 18,084
  • 3
  • 27
  • 42
  • Why answer this instead of directing the OP to the cannonical async reference question? It doesn't matter if the OP is using typescript or not. What matters is that the OP doesn't quite understand how async programming works. – zero298 May 02 '18 at 14:26
  • this solution has helped me. Thank you – Ante Ereš May 02 '18 at 14:30