Google Places Api批量请求Javascript

时间:2017-01-30 22:15:28

标签: javascript google-maps google-maps-api-3 google-places-api google-places

所以我听说没有真正干净的方法将请求referenced here批量发送到GooglePlacesAPI;了解。

但必须有一个解决方法。

const retrievePlaces = (google, map, request) => {
  var places = [];
  var newPlaces = []
  var service = new google.maps.places.PlacesService(map);

  return new Promise(function(resolve, reject) {
    service.nearbySearch(request, function(results, status){

    if( status == "OK" ){
      for (var i = 0; i < results.length; i++) {
          var place = results[i];
          places.push(place);
        }
        resolve(places);
      }
    });
  });
}

我使用上面的函数首先检索我的位置(这很好)。然后我用:

const retrieveDetails = ( google, map, places ) => {

   var gmap = {
     map: map,
     google: google
   };

   var placeIds = places.map(function(place){
     return { placeId: place.place_id }
   });

   var promiseArray = placeIds.map( place => getPlaceDetailsPromise( place, gmap )
                                        .then(  res => ({res}) ) 
                                        .catch( err => ({err}) ) );

   Promise.all(promiseArray)
     .then(results => {
       console.log(results);
   });

 }

const getPlaceDetailsPromise = (obj, gmap) => new Promise((resolve, reject) => {
   var service = new gmap.google.maps.places.PlacesService(gmap.map);

   service.getDetails(obj, (place, status) => {
     if (status === google.maps.places.PlacesServiceStatus.OK) {
       console.log(" Status OK", place);
       resolve(place);   
     } else {
       console.log("Not OK");
     }
  });
});

尝试从PlaceDetailsAPI检索所有地点的详细信息。糟糕的是,它实际上在某种程度上起作用,但它总是只返回9个响应,而不是更多。而且他们出了故障。

有没有人对如何检索每个地方的详细信息有任何见解?

2 个答案:

答案 0 :(得分:1)

Maps JavaScript API客户端服务具有每个会话限制。这在文档的以下部分中提到:

https://developers.google.com/maps/documentation/javascript/geocoding#UsageLimits

  

每个用户会话应用的速率限制,无论有多少用户共享同一个项目。

     

每会话速率限制可防止对批处理请求(例如批量地理编码)使用客户端服务。对于批量请求,请使用Google Maps Geocoding API网络服务。

遗憾的是,文档并未在文档的places库部分中包含此通知,但它的工作原理相同。

据我所知,最初你有一堆10个请求。一旦存储桶为空,请求被拒绝。铲斗以每秒1次请求的速度重新填充。因此,您必须限制您的地点详细信息请求,以保持在每个会话限制允许的范围内。或者,您可以尝试在服务器端实现批处理位置请求,您将有50个查询每秒(QPS)限制。

答案 1 :(得分:0)

感谢@xomena,对于任何可能偶然发现这个问题的人来说,有一种方法可以做到这一点,它涉及@xomena之前提到的内容。它有点脏,可能非常低效,但做我需要它做的事情。

我最终做了一个小的ajax / curl开始来解决我的问题并解决我遇到的CORS问题。我创建了一个服务器端代理,它采用格式化的google api请求uri(通过我的一个函数从ajax发送)并返回详细信息对象。

之后,一切都像魅力一样。更新的代码如下。

const retrievePlaces = (google, map, request) => {
  var places = [],
      newPlaces = [],
      service = new google.maps.places.PlacesService(map);

  return new Promise(function(resolve, reject) {
    service.nearbySearch(request, function(results, status){
      if( status == "OK" ){
        for (var i = 0; i < results.length; i++) {
          var place = results[i];
          places.push(place);
        }
        resolve(places);
      }
     });
  });
}

const retrieveDetails = (google, map, places, api) => {

  var gmap = { map: map, google: google, api_key: api },
      placeDetails = [],
      placeIds = places.map(getPlaceIds),
      promiseArray = placeIds.map(getPlaceDetails);

  function getPlaceIds(place){
    return { placeId: place.place_id }
  }

  function getPlaceDetails(place){
    getPlaceDetailsPromise( place, gmap )
      .then(  res => ({res}) ) 
      .catch( err => ({err}) );
  }

  return Promise.all(promiseArray);

}

const getPlaceDetailsPromise = ( obj, gmap ) => new Promise((resolve, reject) => {

  var url = `https://maps.googleapis.com/maps/api/place/details/json?placeid=${obj.placeId}&key=${gmap.api_key}`,
      qsObj = Qs.parse({ url: url }),
      qsString = Qs.stringify(qsObj),
      headerConfig = { 
        headers: { 
          "Content-Type": "application/x-www-form-urlencoded" 
        } 
      };

  function resolveDetails(res){
    var result = res.data;
    resolve($.parseJSON(result));
  }

  axios.post('/a/random/path', qsString, headerConfig ).then(resolveDetails);

});

然后是php中的代理:

<?php 
 /* proxy.php */
 $url = $_POST["url"];

 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL, $url);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 $result = curl_exec ($ch);
 curl_close ($ch);

 $result = json_encode($result);

 echo $result;

 die();
?>

当然,如果您将其插入代码中并将其播放到代码中,那么这将无效。如果有人找到一种更好的方式,我很乐意看到你是怎么做到的,那将来很有必要知道。