【问题标题】:Google Places API Web Service Server Side SolutionGoogle Places API Web 服务服务器端解决方案
【发布时间】:2017-08-26 23:37:44
【问题描述】:

我已经为此苦苦挣扎了几天 - 我已经让它按我想要的方式工作,但是我一直遇到障碍,我将在下面描述。到了这种地步,我只需要向有必要经验的人寻求一些建议。

所以这就是我最终想要实现的目标:

  1. 网页加载,用户在 Google 地图上看到他们的本地区域
  2. 地图旁边有一个品牌列表,例如“Tesco”和 以“沃尔玛”为例
  3. 当用户点击沃尔玛时,他们会 在地图上查看当地所有沃尔玛商店 - 当地图 单击标记,弹出窗口将包含商店名称、地址 等

在功能方面真的很简单。

我最初使用 Google Maps JavaScript APIGoogle Places API JavaScript 库

我的基本功能正常工作,但遇到了OVER_QUERY_LIMIT 问题。

我发现这是因为同时发出请求(与每日使用限制无关);例如,当用户点击“沃尔玛”时,试图同时在地图上显示约 10 多家商店被 Google 阻止。

根据我的研究,看来我必须改用 Google Maps API Web 服务

如果在特定时间段内发出过多请求,API 会返回 OVER_QUERY_LIMIT 响应代码。每个会话的速率限制阻止将客户端服务用于批处理请求。 对于批量请求,请使用 Maps API 网络服务

因此,我还第二次使用 Google Places API Web 服务完成了所有工作,对此我感到非常满意。我正在使用 AJAX 从 Google 请求 JSON,但现在我收到以下控制台错误:

XMLHttpRequest 无法加载 https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=53.000403,-1.129625&radius=10000&name=Sainsbury's|Debenhams&key=AIzaSyBJPuiaP0Xptia5x3aKgizYLkzqMTAdMMg。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许访问 Origin 'null'。

我知道我收到此错误是因为我从不同的服务器/域请求。这是我的代码,目前我只是在本地运行:

accessURL = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location="+userCords.latitude+","+userCords.longitude+"&radius=10000&name=Sainsbury's|Debenhams&key=AIzaSyBJPuiaP0Xptia5x3aKgizYLkzqMTAdMMg";	

$.ajax({
  type: "GET",
  contentType: "application/json; charset=utf-8",
  url: accessURL,
  dataType: 'json',
  success: function (data) {

    $.each(data.results, function (i, val) {
      storeId.push(val.place_id);
      storeName.push(val.name);
    });

    //Now, use the id to get detailed info
    $.each(storeId, function (k, v){
      $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        url: "https://maps.googleapis.com/maps/api/place/details/json?placeid="+v+"&key=AIzaSyBJPuiaP0Xptia5x3aKgizYLkzqMTAdMMg",
        dataType: 'json',
        success: function (data) {

          var latitude = data.result.geometry.location.lat;
          var longitude = data.result.geometry.location.lng;

          //set the markers.	  
          myLatlng = new google.maps.LatLng(latitude,longitude);

          allMarkers = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: data.result.name,
            html: '<div class="marker-content">' +
                '<p>'+data.result.name+'</p>' +
                  '<p>'+data.result.formatted_address+'</p>' +
                '</div>'
          });

          //put all lat long in array
          allLatlng.push(myLatlng);

          //Put the markers in an array
          tempMarkerHolder.push(allMarkers);

          google.maps.event.addListener(allMarkers, 'click', function () {
            infowindow.setContent(this.html);
            infowindow.open(map, this);
          });

          //  Make an array of the LatLng's of the markers you want to show
          //  Create a new viewpoint bound
          var bounds = new google.maps.LatLngBounds ();
          //  Go through each...
          for (var i = 0, LtLgLen = allLatlng.length; i < LtLgLen; i++) {
            //  And increase the bounds to take this point
            bounds.extend (allLatlng[i]);
          }
          //  Fit these bounds to the map
          map.fitBounds (bounds);


        }
      });
    }); //end .each
  }
});

为了测试,我在 API 访问 url 前使用了这个 https://crossorigin.me 来暂时解决这个问题,但现在我实际上需要正确解决这个问题。

经过一番研究,我看到很多人建议将dataType 更改为jsonp。但是当我这样做时,我收到以下控制台错误:

https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=53.041981899999996,-1.1898794&radius=10000&name=Sainsbury%27s|Debenhams&key=AIzaSyBJPuiaP0Xptia5x3aKgizYLkzqMTAdMMg&callback=jQuery111309486707670378429_1491079656734&_=1491079656735:2 Uncaught SyntaxError: Unexpected token :

在对最新的错误进行更多研究之后,我看到了诸如“看起来 api 不支持 ajax 或 jsonp 的地方”之类的东西,这在我已经全部工作之后非常烦人!

然后我看到了这个:

Google Places API 网络服务用于服务器应用程序。如果您正在构建客户端应用程序,请查看适用于 Android 的 Google Places API 和 Google Maps JavaScript API 中的 Places Library。

这意味着我现在已经绕了一圈!

我想我必须制定一个服务器端解决方案而不是客户端解决方案。但老实说,我不知道从这里去哪里,也找不到任何在线内容可以为我指明正确的方向。

谁能告诉我下一步该怎么做? “服务器端解决方案”会是什么样子?我已经走到这一步了,我现在真的不想放弃!任何帮助将不胜感激!

【问题讨论】:

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


【解决方案1】:

要解决此问题,您应该构建自己的中间服务器,该服务器将向 Google 发送请求(服务器端请求)并将 JSON 响应传递回您的客户端应用程序。换句话说,您应该构建一个代理来避免 CORS 问题。

如何构建代理服务器完全取决于您。选择您熟悉的技术(Java、Python、NodeJs 等)并实现服务器端代码。

客户端代码向中间服务器发送请求,中间服务器向谷歌发送HTTPS请求并将响应返回给客户端。

GitHub 上有几个有用的库,您可以在服务器端使用 NodeJs、Java、Python 或 Go:

https://github.com/googlemaps/google-maps-services-js

https://github.com/googlemaps/google-maps-services-java

https://github.com/googlemaps/google-maps-services-python

https://github.com/googlemaps/google-maps-services-go

希望对您有所帮助!

【讨论】:

  • 感谢您的回复!我不知道从哪里开始构建自己的代理服务器,您能否指出一些可以帮助我的入门级指南/教程/文档的方向?
  • 这里有一篇关于用nodejs搭建http web服务器的介绍文章:blog.xervo.io/build-your-first-http-server-in-nodejs
  • 再次感谢,这对我来说都是全新的。当我将文件放在实时服务器上时会发生什么,它们的工作方式是否相同?使用 nodejs 构建 http Web 服务器与仅使用 MAMP 之类的东西有什么区别?对 Google 的服务器端请求不能用 PHP 编写吗?同样,我们将不胜感激任何进一步的帮助。
【解决方案2】:

我收到了关于发送 90 个请求的相同 OVER_QUERY_LIMIT 消息,这是从 stackOverFlow 中整理出来的一些解决方案:

  1. 延迟请求
  2. 如果 OVER_QUERY_LIMIT,重试此请求
  3. 将请求从clientService更改为webService.See more from google api document

所以我尝试延迟我的请求,这不能阻止 OVER_QUERY_LIMIT ,但会大大降低频率。这是我关于 google map api 方向的核心功能,就像你的 google map place Api 一样。

function calculateDirections( directionsService, requestList, responseList, deferred, recursiveCount ) {
            var deferred = deferred || $q.defer();
            var responseList = responseList || [];
            var recursiveCount = recursiveCount || 0;
            var directionRequest = {
                origin: requestList[ recursiveCount ].origin,
                destination: requestList[ recursiveCount ].destination,
                waypoints: requestList[ recursiveCount ].waypoints,
                optimizeWaypoints: false,
                travelMode: google.maps.TravelMode.DRIVING
            };

            directionsService.route( directionRequest, function ( response, status ) {
                if ( status === google.maps.DirectionsStatus.OK ) {
                    responseList.push( response );
                    if ( requests.length > 0 ) {
                        //delay google request,millisecond
                        setTimeout( function () {
                            recursiveCount++;
                            calculateDirections( directionsService, requests, responseList, deferred, recursiveCount );
                        }, recursiveCount * 10 + 500 );

                    } else {
                        deferred.resolve( responseList );
                    }
                }else if( status === google.maps.DirectionsStatus.OVER_QUERY_LIMIT ){
                    //try again google request
                    setTimeout( function () {
                        calculateDirections( directionsService, requests, responseList, deferred, recursiveCount );
                    }, recursiveCount * 10 + 500 );
                } else {
                    var result = {};
                    result.status = status;
                    deferred.reject( result );
                }

            } );

            return deferred.promise;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 2011-04-15
    • 1970-01-01
    • 2015-11-08
    • 2012-06-17
    • 2016-11-21
    • 1970-01-01
    相关资源
    最近更新 更多