Google Maps标记点击报错:Missing parameter. You must specify placeId
问题排查与解决:Google Maps Marker点击触发placeId缺失错误
问题概述
原本正常运行的Google Maps相关代码,调整后出现「Unhandled Promise Rejection: Error: Missing parameter. You must specify placeId」错误,恢复原代码后问题依旧。点击Marker弹出InfoWindow时触发报错,排查确认marker.placeId的值为undefined。
成因分析
- placeId存取方式不匹配:代码中通过
MarkerPlaceID.set(marker, place.placeId)将placeId存入自定义Map,但在handleMarkerClick中直接尝试读取marker.placeId——Google Maps的Marker对象本身没有内置placeId属性,这种读取方式无法获取到之前存储的值。 - 浏览器缓存残留:恢复原代码后,浏览器可能仍加载了旧的缓存文件,导致修改未生效。
- 潜在数据缺失(次要):虽然之前正常运行,但
textSearch返回的部分place对象可能存在placeId为空的情况,不过这并非当前报错的直接原因。
解决办法
方案1:统一placeId的存取方式
方式A:直接给Marker挂载自定义属性(更简洁)
修改搜索算法中的代码,将MarkerPlaceID.set(marker, place.placeId)替换为直接给marker添加属性:
// 替换原有的 MarkerPlaceID.set(marker, place.placeId); marker.placeId = place.placeId;
这样handleMarkerClick中marker.placeId的读取逻辑就能正常工作。
方式B:使用Map的get方法读取
如果坚持使用MarkerPlaceID这个Map存储,修改handleMarkerClick中的placeId获取逻辑:
// 替换原有的 const request = { placeId: marker.placeId, ... }; const placeId = MarkerPlaceID.get(marker); const request = { placeId: placeId, fields: [ "name", "formatted_address", "photos", "formatted_phone_number", "website", "opening_hours", "rating", "reviews", ], };
方案2:清除浏览器缓存
- 按
Ctrl+Shift+R(Windows/Linux)或Cmd+Shift+R(Mac)强制刷新页面,加载最新代码; - 或在浏览器开发者工具的「网络」面板中勾选「禁用缓存」,重新加载页面。
方案3:添加数据校验(可选)
为避免因place对象无placeId导致的后续报错,在创建Marker前添加校验:
results.forEach((place) => { if (!place.name.includes("ديوان") && place.placeId) { // 新增placeId校验 // 创建Marker及后续逻辑 } });
修改后的关键代码示例
搜索算法(使用自定义属性方式)
const service = new google.maps.places.PlacesService(map); service.textSearch(request, (results, status) => { if (status === google.maps.places.PlacesServiceStatus.OK) { results.forEach((place) => { if (!place.name.includes("ديوان") && place.placeId) { const marker = new google.maps.Marker({ map, position: place.geometry.location, }); const infoWindow = new google.maps.InfoWindow(); // 直接挂载placeId到marker对象 marker.placeId = place.placeId; marker.addListener("click", () => { handleMarkerClick(marker); resultRowCLick(marker); }); google.maps.event.addListener(map, 'click', function() { infoWindows.forEach(function(infoWindow) { infoWindow.close(); }); }); markers.push(marker); addNewResultRow(place.name, place.formatted_address, marker); } }); console.log("Nearby search results:", results); } else { console.error("Error performing nearby search:", status); } });
handleMarkerClick函数(无需修改,若使用方案A)
function handleMarkerClick(marker) { infoWindows.forEach((infoWindow) => { infoWindow.close(); }); let infoWindow = new google.maps.InfoWindow(); window.addEventListener('keydown', (event) => { if (event.keyCode === 27) { infoWindow.close(); } }); const request = { placeId: marker.placeId, fields: [ "name", "formatted_address", "photos", "formatted_phone_number", "website", "opening_hours", "rating", "reviews", ], }; const service = new google.maps.places.PlacesService(map); service.getDetails(request, (place, status) => { if (status === google.maps.places.PlacesServiceStatus.OK) { let content = '<div style="max-width: 250px;">'; if (place.photos && place.photos.length > 0) { const photoUrl = place.photos[0].getUrl(); content += '<div class="image-container">'; content += `<img src="${photoUrl}" alt="${place.name}" style="max-width: 250px; max-height: 150px;">`; content += '</div>'; } content += `<h2>${place.name}</h2>`; content += `<p>Address: ${place.formatted_address}</p>`; if (place.website) { content += `<p>Website: <a href="${place.website}" target="_blank">${place.website}</a></p>`; } if (place.formatted_phone_number) { content += `<p>Phone: ${place.formatted_phone_number}</p>`; } if (place.opening_hours) { content += `<div class="times">` content += `<br><p>Opening Hours:</p>`; content += `<p>${place.opening_hours.weekday_text.map(line => ` ${line}`).join("<br>")}</p>`; content += `</div>` } if (place.rating) { content += '<div class="rating-container">'; content += '<p>'; content += `rating: ${place.rating}`; for (let i = 0; i < place.rating; i++) { content += ' <i class="fa fa-star"></i>'; } content+= "</p>" content += '</div>'; } if (place.reviews && place.reviews.length > 0) { content += '<p>Reviews:</p>'; content += '<ul>'; place.reviews.forEach((review) => { if (review.text && review.text.trim().length > 0) { content += `<li class="review-item">${review.text}</li>`; } }); content += '</ul>'; } content += '</div>'; infoWindow.setContent(content); infoWindow.open(map, marker); infoWindows.push(infoWindow); } else { console.error("Error fetching Place Details:", status); } }); }
内容的提问来源于stack exchange,提问作者Nayef Alhajraf
相关产品推荐
相关产品推荐

