Google Places (New) Autocomplete Data API 遇尾随空格无法正常工作问题求助
Fix for Google Places Autocomplete Disappearing on Trailing Spaces
我来帮你解决这个自动补全建议消失的问题,先分析问题根源,再给出修复后的完整代码。
问题原因分析
- Google Places API v1 必填字段缺失:你当前的请求没有添加
X-Goog-FieldMask请求头,这是Google Places API v1的必填项。如果不指定字段掩码,API可能不会返回suggestions数据,导致请求成功但结果为空,最终显示"No results found"。 - 重复请求与竞态条件:每次输入事件触发时,哪怕trim后的查询内容和上一次完全相同(比如添加尾随空格),你都会重新调用API。这不仅浪费资源,还可能因为网络延迟导致旧请求覆盖新结果,或者返回空结果时清空了之前的有效建议。
- 输入事件逻辑瑕疵:添加尾随空格时,trim后的查询和之前一致,但重复调用无字段掩码的API会返回空结果,导致建议被替换成"No results found"。而聚焦时只是显示之前的结果容器,并没有重新调用API,所以如果之前有未被覆盖的有效结果,就会正常显示。
修复后的代码
JavaScript
// 缓存上一次的查询和结果,避免重复请求 let lastQuery = ""; let lastPredictions = []; async function autocomplete(query) { // 如果查询内容和上一次一致,直接返回缓存结果 if (query === lastQuery) { return lastPredictions; } const response = await fetch( "https://places.googleapis.com/v1/places:autocomplete", { method: "POST", headers: { "Content-Type": "application/json", "X-Goog-Api-Key": "AIzaSyC-NJ9bxaWdlLQBmHxR-QDgwFXsbGX0oKg", // 添加字段掩码,指定需要返回的字段 "X-Goog-FieldMask": "suggestions.placePrediction.text" }, body: JSON.stringify({ input: query, }) } ); const data = await response.json(); // 更新缓存 lastQuery = query; lastPredictions = data.suggestions || []; return lastPredictions; } const input = document.querySelector("#address"); const results = document.querySelector("#results"); input.addEventListener("input", async () => { const trimmedQuery = input.value.trim(); if (trimmedQuery.length < 3) { results.innerHTML = "<li class='three'>Please enter at least 3 characters</li>"; // 清空缓存 lastQuery = ""; lastPredictions = []; return; } const predictions = await autocomplete(trimmedQuery); if (!predictions || predictions.length === 0) { results.innerHTML = "<li class='three'>No results found</li>"; return; } results.innerHTML = ""; // 移除可能存在的"No results found"提示 const noResultEl = document.querySelector(".three"); if (noResultEl) { noResultEl.classList.add("hidden"); } predictions.forEach(prediction => { const li = document.createElement("li"); li.textContent = prediction.placePrediction.text.text; li.dataset.action = "select-address"; results.appendChild(li); }); }); function select_address(event) { input.value = event.textContent; // 选择地址后隐藏结果列表 results.classList.add("hidden"); } const ACTIONS = { "select-address": select_address }; document.addEventListener("click", (click_event) => { const target = click_event.target.closest("[data-action]"); if (!target) return; const action_name = target.dataset.action; console.log(`Action triggered: ${action_name}`); if (ACTIONS[action_name]) { ACTIONS[action_name](target, click_event); } }); input.addEventListener("focus", async function() { results.classList.remove("hidden"); // 如果当前trim后的查询符合长度要求且没有缓存,重新调用API const trimmedQuery = input.value.trim(); if (trimmedQuery.length >=3 && lastQuery !== trimmedQuery) { const predictions = await autocomplete(trimmedQuery); if (predictions && predictions.length > 0) { results.innerHTML = ""; predictions.forEach(prediction => { const li = document.createElement("li"); li.textContent = prediction.placePrediction.text.text; li.dataset.action = "select-address"; results.appendChild(li); }); } } }); document.addEventListener("click", (event) => { if (!input.contains(event.target) && !results.contains(event.target)) { results.classList.add("hidden"); }; });
关键修复点说明
- 添加字段掩码:在请求头中加入
X-Goog-FieldMask,确保API返回我们需要的suggestions数据。 - 查询缓存机制:新增
lastQuery和lastPredictions变量,缓存上一次的查询内容和结果,避免重复请求相同的查询。 - 优化输入事件逻辑:当trim后的查询长度不足3时,显示提示并清空缓存;查询有效时优先使用缓存结果,减少不必要的API调用。
- 聚焦时的补全逻辑:聚焦时如果当前查询有效且无缓存,重新调用API获取结果,确保显示最新的建议。
额外建议
- 不要在前端代码中直接暴露Google API密钥,建议通过后端代理来调用API,避免密钥泄露。
- 可以添加防抖处理(比如用
setTimeout延迟500ms调用API),减少用户快速输入时的API请求次数。
内容的提问来源于stack exchange,提问作者Daniel Phillion
相关产品推荐
相关产品推荐

