Estoy haciendo todo lo posible para que mi promesa JS funcione, pero no puedo devolver ningún resultado.

geocodeAddress = function(streetAddress){

    var geocodeObject = new Promise(function(resolve, reject) {

      // async call to Google's Geocoder - takes street address
      // and returns GPS coordinates

      var gpsPosition = {};
      geocoder = new google.maps.Geocoder();
      if (geocoder) {
        // console.log("This is the street address");
        // console.log(streetAddress);
        geocoder.geocode({'address': streetAddress}, function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            if (results[0]) {
              console.log("got GPS coordinates for the streetAddress!");
              gpsPosition.B = results[0].geometry.location['B'];
              gpsPosition.k = results[0].geometry.location['k'];
              console.log(gpsPosition);
              resolve(gpsPosition);
            } else {
              alert("No results found");
              reject(Error("It broke"));
            }
          } else {
            alert("Geocoder failed due to: " + status);
            reject(Error("It broke"));
          }
        });
      }

    });

    geocodeObject.then(function(result) {
      console.log("This is the gpsPosition");
      console.log(result); // this console logs the result just fine
      return result;       // however the result can't be returned
    }, function(err) {
      console.log(err); // Error: "It broke"
    });

}

Si lo hago geocodeAddress("1600 Amphitheatre Pkwy, Mountain View, CA 94043"), la función puede consolar.log el resultado, pero no puede devolverlo en la línea siguiente.

He estado usando estos como referencias para promesas:

http://www.html5rocks.com/en/tutorials/es6/promises/#toc-javascript-promises

http://www.sitepoint.com/overview-javascript-promises/

Pero el problema con estos tutoriales (al menos el segundo) es que nunca devuelven explícitamente el resultado. La consola lo registra (que funciona) o lo usa inmediatamente dentro de una función.

1
fuzzybabybunny 1 sep. 2014 a las 07:37

2 respuestas

La mejor respuesta

Con cualquier tipo de llamada asíncrona, debe manejar el resultado con una función de devolución de llamada en lugar de buscar la función asíncrona para devolver un valor. La razón se debe a la naturaleza misma de una operación asíncrona ... el hilo debe poder pasar a la siguiente tarea y manejar el resultado de la operación asincrónica con una función de devolución de llamada cuando haya terminado. La única forma en que una operación asíncrona podría devolver el resultado de la operación asincrónica es si la computadora se aferró al hilo asíncrono hasta que terminó, lo que la convertiría en una operación de sincronización. Vea si esto ayuda:

function geocodeAddress(streetAddress) {

    new Promise(function(resolve, reject) {

      // async call to Google's Geocoder - takes street address
      // and returns GPS coordinates

      var geocoder = new google.maps.Geocoder();
      geocoder.geocode({'address': streetAddress}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          if (results[0]) {
            resolve({B: results[0].geometry.location['B'],
                     k: results[0].geometry.location['k']});
          } else {
            reject(Error("It broke"));
          }
        } else {
          reject(Error("It broke"));
        }
      });
    })
    .then(
      // this is the Promise resolve handler
      function(result) {
        handleGeocodeResult(result);
      },
      // this is the Promise reject handler
      function(err) {
        console.log(err); // Error: "It broke"
      });
}

function handleGeocodeResult(result) {
  // for illustration only... this function should actually
  // *BE* the Promise resolve handler.
  console.log("This is the gpsPosition");
  console.log(result); // this console logs the result just fine
}

geocodeAddress("1600 Amphitheatre Pkwy, Mountain View, CA 94043");

JSFiddle

1
ic3b3rg 1 sep. 2014 a las 07:05

El problema es la forma en que está utilizando la función geocodeAddress. Está esperando una promesa de regresar en la próxima línea. Lo que realmente debería hacer es devolver la promesa de geocodeAddress y utilizarla como una promesa.

geocodeAddress = function(streetAddress){

  // sorry i omitted the resolve here, for clarity, here more explicit:
  var geocodeObject = new Promise(function (resolve, reject) {
      resolve('hello world');
  });

  // return the promise
  return geocodeObject.then(function() {});
};

// use the geocodeAddress as a promise
var geoAddressPromise = geocodeAddress('alasjdf');

// see geoAddressPromise is a promise object, you can't console log the result.
// you can call 'then' method on it.

geoAddressPromise.then(function(result) {
   // put your code here instead of the next line.
   // you can console.log the result here
   console.log(result);

   // this result is the value you pass to 'resolve' callback inside the promise.
   // in this example it s "hello world".
});
0
user3995789 1 sep. 2014 a las 06:15