如何使用promises获取Google商家信息数据?

时间:2016-04-08 23:03:57

标签: javascript google-maps promise deferred google-places

我正在尝试获取多个Google商家信息的数据,然后为地图上的每个地点绘制标记。我正在尝试使用promises等到更新地图之前检索到每个地方的数据。这就是我所拥有的:

var service = new google.maps.places.PlacesService(map),
    promises = [],
    promise = '',
    searchCallback = function(results, status) {

        if(status == google.maps.places.PlacesServiceStatus.OK) {

            for(var i = 0; i < results.length; i++) {

                var place = results[i];

                // this works
                console.log(place);

                // resolve the promise
                promise.resolve(place);
            }
        }
    }

$('li').each(function(index) {

    promise = $.Deferred(),

    var lng = $(this).attr('data-longitude'),
        lat = $(this).attr('data-latitude'),
        name = $(this).text(),
        latLng = new google.maps.LatLng(lat, lng),
        request = {
            location: latLng,
            radius: '500',
            query: name
        };

    // push promise into array
    promises.push(promise);

    // get data about place
    service.textSearch(request, searchCallback);
}

// when all promises are complete
$.when.apply($, promises).then(function(data) {
    console.log(data);
});

我的PlacesService工作正常。我可以console.log(place)我看到Google返回的对象,但是当我在console.log(data)回调中尝试$.when时,data会返回undefined。看来我的承诺不能正常运作。我错过了什么?

1 个答案:

答案 0 :(得分:0)

promise作为外部var:

编写
  • 最多只能有一个延期分配给promise
  • 完成$('li').each()循环后,Deferred将是循环中分配的 last
  • 成功返回结果的第一个service.textSearch()将导致最后一个承诺解决。
  • 随后的成功将尝试解决相同的承诺,但未能这样做,因为承诺只能解决一次。

因此,promises数组将正确包含所有生成的Deferred,但只会解析最后一个。所有其他Derferreds将保持&#34;待定&#34;并且$.when.apply($, promises)永远无法解决。

此类问题的推荐策略是:

  • 在最低级别宣传。
  • 处理最高级别的数据。

对于错误处理,有一个设计选择。你可以:

  • 允许任何个别异步错误来破坏整个edeavour,或
  • 通过处理个别异步错误并注入默认值来恢复。

在这种情况下,第二种选择似乎是最合适的。

var service = new google.maps.places.PlacesService(map);

// Promisify service.textSearch() as service.textSearchAsync()
// (lowest level)
service.textSearchAsync = function(options) {
    return $.Deferred(function(dfrd) {
        service.textSearch(options, function(results, status) {
            if(status == google.maps.places.PlacesServiceStatus.OK) {
                promise.resolve(results);
            } else {
                promise.reject(new Error(status));
            }
        });
    }).promise();
};

// Map the 'li' elements to an array of promises, exploiting the low level utility.
// (intermediate level)
var promises = $('li').map(function(index) {
    return service.textSearchAsync({
        location: new google.maps.LatLng($(this).data('latitude'), $(this).data('longitude')),
        radius: '500',
        query: $(this).text()
    }).then(null, function(error) {
        console.error(error);
        return $.when([]); // error recovery (deliver an empty array) such that any individual failure of `service.textSearch()` doesn't scupper the whole endeavour.
    });
}).get();// .get() is necessary to remove the jQuery wrapper returned by $('li').map()

// Aggregate the promises then handle the data gathered
// (highest level)
$.when.apply($, promises).then(function() {
    console.log(arguments); // jQuery.when() delivers data 'spread' into the arguments of its .then() callback
    var i, j, results, place;
    for(i=0; i<arguments.length; i++) {
        results = arguments[i];
        for(j=0; j<results.length; j++) {
            place = results[j];
            console.log(place);
            // now plot `place` as a marker on the map.
        }
    }
});