Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a value from a 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.com/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,component or component",
            "UNKNOWN_ERROR": "There was an error somewhere on Google's servers" 
    };
    if(address)
        promise=Q($.ajax({
            type: "GET",
            url: "https://maps.googleapis.com/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?

like image 476
vamsiampolu Avatar asked Aug 27 '14 14:08

vamsiampolu


People also ask

How do you return a value from a promise?

Promise resolve() method: If the value is a promise then promise is returned. If the value has a “then” attached to the promise, then the returned promise will follow that “then” to till the final state. The promise fulfilled with its value will be returned.

Can you return from a promise?

Promises don't "return" values, they pass them to a callback (which you supply with . then()). It's probably trying to say that you're supposed to do resolve(someObject); inside the promise implementation. Then in your then code you can reference someObject to do what you want.

What does returns a promise mean?

Returns a new Promise object that is resolved with the given value. If the value is a thenable (i.e. has a then method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise, the returned promise will be fulfilled with the value.

Does promise then return a promise?

Promise.prototype.then() The then() method returns a Promise . It takes up to two arguments: callback functions for the fulfilled and rejected cases of the Promise .


2 Answers

If 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.com/maps/api/geocode/json?address=" + address + "&key=API_KEY"
    }));
    return promise.then(function(data) {
        // whatever you return here will also become 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);
});
like image 75
Willem D'Haeseleer Avatar answered Sep 19 '22 09:09

Willem D'Haeseleer


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 computation:
// 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!

like image 23
Bergi Avatar answered Sep 21 '22 09:09

Bergi