【问题标题】:Google Places Api Batch Requests JavascriptGoogle Places Api 批量请求 Javascript
【发布时间】:2017-01-30 22:15:27
【问题描述】:

所以我听说没有真正干净的方法来批量请求referenced hereGooglePlacesAPI;明白了。

但必须有一个解决办法。

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 个响应而不再返回。此外,它们出现故障。

是否有人对如何检索每个地点的详细信息有任何见解?

【问题讨论】:

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


    【解决方案1】:

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

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

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

    每个会话的速率限制会阻止将客户端服务用于批量请求,例如批量地理编码。对于批量请求,请使用 Google Maps Geocoding API 网络服务。

    不幸的是,文档的位置库部分中没有包含此通知,但它的工作原理相同。

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

    【讨论】:

      【解决方案2】:

      感谢@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();
      ?>
      

      当然,如果您将其插入并播放到您的代码中,这将不起作用,但想法就在那里。如果有人找到更好的方法,我很想看看你是怎么做到的,将来知道会很好。

      【讨论】:

        猜你喜欢
        • 2012-09-20
        • 1970-01-01
        • 2013-07-24
        • 1970-01-01
        • 2022-01-10
        • 1970-01-01
        相关资源
        最近更新 更多