通过 GooglePlaces 自动完成的地理搜索:在 X 个字符后开始请求

Geosearch via GooglePlaces Autocomplete: Start requests after X chars

我正在使用以下代码通过 Geosearch 使用 Google Places API:

进行“智能”自动完成
var input = 'field_18';
google.maps.event.addDomListener(document.getElementById(input), 'keydown', function(event) {
    if (event.keyCode === 13) {
        event.preventDefault();
    }
});

var ppx_autocomplete = new google.maps.places.Autocomplete((document.getElementById(input)), { types: ['geocode'] });
ppx_autocomplete.setFields(['geometry', 'formatted_address']);
google.maps.event.addListener(ppx_autocomplete, 'place_changed', function () {
    var place = ppx_autocomplete.getPlace();
    document.getElementById(input).value = place.formatted_address;
    var lat = place.geometry.location.lat();
    var lng = place.geometry.location.lng();
    document.getElementById('pp_18_geocode').value = latlng;
});

很普通也很直接。

缺点是:自动完成会在输入前 2 或 3 个字母后立即开始,导致对 Google 的大量请求,因此导致我的 API 键消耗。

有什么方法可以限制请求的数量,例如通过仅在 5 个键入的字母之后发送请求并且可能在一些延迟时间之后,例如当用户仍在键入时不发送请求...

您正在查找的内容可以完成,但您需要使用自动完成服务 [1] 而不是自动完成小部件 [2]。下面是一个例子,等到输入第五个字符才发出请求,然后每增加 2 个字符就发出一个。可以在“在此处编辑参数”行编辑字符数。您需要插入自己的 API 密钥。类似的例子在 https://codepen.io/ecglover8/pen/ExPqdNd 每 3 个字符执行一次。

由于您不会使用自动完成小部件,因此您需要自己处理会话令牌 [3](未显示)。从价格的角度来看,您是否需要代币取决于您打算如何使用预测 [4]。此示例实际上使用来自预测的地点 ID 发出地理编码 API 请求并显示 lat/long.

[1] https://developers.google.com/maps/documentation/javascript/places-autocomplete#place_autocomplete_service

[2] https://developers.google.com/maps/documentation/javascript/places-autocomplete#add-autocomplete

[3] https://developers.google.com/maps/documentation/javascript/places-autocomplete#session_tokens

[4] https://developers.google.com/maps/documentation/places/web-service/usage-and-billing#ac-per-request

//declare constants
const ac = document.getElementById("ac");
const g = document.getElementById("geocoded");
const results = document.getElementById("results");

//listen for typing into input box
ac.addEventListener("input", ACRequest);

//show resulting predictions 
const displayPredictions = function(predictions, status) {
  results.innerHTML = "";
  g.innerHTML = "";
  if (status != google.maps.places.PlacesServiceStatus.OK) {
    alert(status);
    return;
  }
  predictions.forEach(prediction => {
    let li = document.createElement("li");
    li.appendChild(document.createTextNode(prediction.description));
    li.dataset.placeid = prediction.place_id;
    li.addEventListener("click", Geo)
    results.appendChild(li);
  });
  let img = document.createElement("img");
  img.setAttribute("src", "https://developers.google.com/maps/documentation/images/powered_by_google_on_white.png");
  results.appendChild(img);
};

//make autocomplete request if input value length divisible by 3
function ACRequest() {
  //edit params here
  if ((ac.value.length > 4) && (ac.value.length % 2 == 1)) {
    const service = new google.maps.places.AutocompleteService();
    service.getPlacePredictions(
      {
        //here is where you can add bounds, componentrestrictions, types, etc
        input: ac.value
      }, displayPredictions
    )
  };
};
function Geo() {
  console.log(this.getAttribute("data-placeid"));
  const geocoder = new google.maps.Geocoder();
  geocoder.geocode(
    {
      "placeId": this.getAttribute("data-placeid")
    }, function(address, status) {
      if (status == "OK") {
        g.innerHTML = address[0].geometry.location
      } else {
        alert("Geocode was not successful for the following reason: " + status);
      }
    });
}
li {
  border: 2px solid blue;
  list-style: none;
  margin: 2px;
  padding: 2px;
}
li:hover {
  border: 2px solid red;
}
.pac-card {
  border-radius: 2px 0 0 2px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  box-sizing: border-box;
  font-family: Roboto;
  margin: 10px 10px 0 0;
  outline: none;
}
.title {
  background-color: #4D90FE;
  color: #FFFFFF;
  font-size: 25px;
  font-weight: 500;
  margin: 10px 0px;
  padding: 6px 12px;
}
<div class="pac-card">
  <div class="title">Autocomplete Makes Requests Every Three Characters</div>
  <input id="ac" size="10" type="text" />
  <ul id="results"></ul>
  <p id="geocoded"></p>
</div>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&libraries=places&v=weekly" async defer></script>