从Promise返回值

Returning a value from a Promise

本文关键字:返回值 Promise      更新时间:2023-09-26

我想调用谷歌地图地理编码API,使用这样的Promise:

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;    
        });
}

当我调用函数makeGeoCodingRequest请求时,我发现我获得了一个promise而不是一个值:

 var geo=makeGeoCodingRequest(address);
 console.log(Q.isPromise(geo));//returns true

为什么promise.en在返回值之前不执行?我如何从这个承诺而不是另一个承诺中获得价值?

如果您依赖promise来返回数据,则必须从函数中返回promise。

一旦调用堆栈中的一个函数是异步的,那么如果您想继续线性执行,那么所有想要调用它的函数也必须是异步的。(async=返回承诺)

请注意,if语句没有大括号,因此,如果条件失败,则仅执行它之后的第一个语句。

我在这个例子中修复了它。请注意我添加的备注。

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;    
    });
}

您必须按以下方式调用makeGeoCodingRequest

makeGeoCodingRequest(address,bounds).then(function(data){
    // this will contain whatever 
    console.log(data);
});

我发现我得到的是承诺而不是价值

是的,因为操作是异步的,并返回一个表示未来值的promise。

为什么promise.en在返回值之前不执行?

因为它是异步的。.then在返回另一个promise之前将(必须)从不执行其回调。

我如何从这个承诺而不是另一个承诺中获得价值?

您正在获取回调中的值:

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!

从承诺中同步获得它是不可能的(许多人都尝试过)。这意味着阻塞执行,而我们不希望这样——让我们保持异步和非阻塞!

您正在从函数makeGeoCodingRequest返回一个promise。根据我的说法,这是一件好事,如果将来需要的话,这可以帮助您链接更多的异步调用。我建议对返回的promise使用.then(),并按照以下方式检查promise是否有任何返回值或错误。

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.
   }
);

如果您希望代码等待异步操作完成后再继续(BAD IDEA-请求完成时页面将冻结),则将async: false添加到ajax请求的参数中。

不过,我的建议是让makeGeoCodingRequest不直接返回任何内容,只需给它一个额外的参数requestCallback,这样它的调用者就可以传入一个函数,该函数将在数据可用时调用。在promise.then函数内部调用该函数及其生成的数据。