I would like to call the Google Maps Geocoding API using a Promise like this:
function makeGeoCodingRequest(address,bounds)
{
/*
Input parameters:
address:a string
bounds: an object of class google.maps.LatLngBounds(southWest,northEast)
This will return a set of locations from the google geocoding library for the given query
*/
var url="=" + address + "&key=AIzaSyD9GBloPC20X-1kWRo7sm_0z5xvCiaSd3c";
var promise,response;
var messages={
"ZERO_RESULTS":"No results were found",
"OVER_QUERY_LIMIT":"We are over the query limit.Wait awhile before making a request",
"REQUEST_DENIED":"Request was denied,probably using a bad or expired API Key",
"INVALID_REQUEST":"Request was sent without the required address,ponent or ponent",
"UNKNOWN_ERROR": "There was an error somewhere on Google's servers"
};
if(address)
promise=Q($.ajax({
type: "GET",
url: "=" + address + "&key=API_KEY"
}));
return promise.then(function(data) {
if (data.status === "OK") return data;
else console.error(messages[data.status]);
return null;
});
}
When I call the function makeGeoCodingRequest
request,I find that I obtain a promise instead of a value:
var geo=makeGeoCodingRequest(address);
console.log(Q.isPromise(geo));//returns true
Why isnt promise.then executed before the value was returned? How can I obtain a value from this promise instead of another promise?
I would like to call the Google Maps Geocoding API using a Promise like this:
function makeGeoCodingRequest(address,bounds)
{
/*
Input parameters:
address:a string
bounds: an object of class google.maps.LatLngBounds(southWest,northEast)
This will return a set of locations from the google geocoding library for the given query
*/
var url="https://maps.googleapis./maps/api/geocode/json?address=" + address + "&key=AIzaSyD9GBloPC20X-1kWRo7sm_0z5xvCiaSd3c";
var promise,response;
var messages={
"ZERO_RESULTS":"No results were found",
"OVER_QUERY_LIMIT":"We are over the query limit.Wait awhile before making a request",
"REQUEST_DENIED":"Request was denied,probably using a bad or expired API Key",
"INVALID_REQUEST":"Request was sent without the required address,ponent or ponent",
"UNKNOWN_ERROR": "There was an error somewhere on Google's servers"
};
if(address)
promise=Q($.ajax({
type: "GET",
url: "https://maps.googleapis./maps/api/geocode/json?address=" + address + "&key=API_KEY"
}));
return promise.then(function(data) {
if (data.status === "OK") return data;
else console.error(messages[data.status]);
return null;
});
}
When I call the function makeGeoCodingRequest
request,I find that I obtain a promise instead of a value:
var geo=makeGeoCodingRequest(address);
console.log(Q.isPromise(geo));//returns true
Why isnt promise.then executed before the value was returned? How can I obtain a value from this promise instead of another promise?
Share Improve this question edited Aug 27, 2014 at 14:54 Willem D'Haeseleer 20.2k10 gold badges68 silver badges103 bronze badges asked Aug 27, 2014 at 14:47 vamsiampoluvamsiampolu 6,63220 gold badges89 silver badges193 bronze badges 1-
promise don't give out value, instead you pass in the function that is going to use the value into the promise using
.then()
– Ishrak M Commented Aug 30, 2020 at 8:38
4 Answers
Reset to default 6If you depend on a promise in order to return your data, you must return a promise from your function.
Once 1 function in your callstack is async, all functions that want to call it have to be async as well if you want to continue linear execution. ( async = return a promise )
Notice that your if
statement does not have braces and thus only the first statement after it will not be executed if the condition fails.
I fixed it in this example. Notice the remarks I added.
if(address){
promise=Q($.ajax({
type: "GET",
url: "https://maps.googleapis./maps/api/geocode/json?address=" + address + "&key=API_KEY"
}));
return promise.then(function(data) {
// whatever you return here will also bee the resolve value of the promise returned by makeGeoCodingRequest
// If you don't want to validate the data, you can in fact just return the promise variable directly
// you probably want to return a rejected promise here if status is not what you expected
if (data.status === "OK") return data;
else console.error(messages[data.status]);
return null;
});
}
You must call makeGeoCodingRequest
in the following fashion.
makeGeoCodingRequest(address,bounds).then(function(data){
// this will contain whatever
console.log(data);
});
I find that I obtain a promise instead of a value
Yes, because the operation is asynchronous and returns a promise which represents the future value.
Why isnt promise.then executed before the value was returned?
Because it's asynchronous. .then
will (must) never execute its callback before it returns another promise.
How can I obtain a value from this promise instead of another promise?
You are getting the value in the callback:
makeGeoCodingRequest(address).then(function(geo) {
console.log(geo)
console.log(Q.isPromise(geo)); // false
// do anything with the value here
})
// if you need to do anything with the result of the callback putation:
// you're getting back another promise for that!
It's impossible to obtain it synchronously from the promise (many have tried). That would mean blocking execution, which we don't want - let's stay async and non-blocking!
You are returning a promise from the function makeGeoCodingRequest. That is a good thing according to me, this helps you chain any more async calls if required in future. What I would suggest is to use a .then() on the returned promise and check if the promise has any returned value or error in the following manner.
var geoPromise = makeGeoCodingRequest(address);
geoPromise.then(
onSuccess(result){
// You can use the result that was passed from the function here..
},
onFailure(response){
// Handle the error returned by the function.
}
);
If you want your code to wait until the asynchronous action is pleted before continuing (BAD IDEA - the page will freeze while the request is pleting) then add async: false
to the ajax request's parameters.
My remendation, though, is to have makeGeoCodingRequest
return nothing directly - and simply give it an extra argument, requestCallback
so that its caller can pass in a function that will be called when the data is available. Call that function, with the resulting data, inside of your promise.then
function.