摘要:电商下单页、外卖收货地址、物流寄件表单——凡是需要用户填写地址的场景,都少不了"输入提示"(也叫地址联想、地址自动补全)。本文以丰图地址输入提示API为例,给出一个可直接改造的前端接入方案:从用户敲下第一个字开始,到防抖处理、缓存复用、无结果兜底、选中后逆地理编码补全,完整走通。最后算清收费:免费1500次体验,按量30元/万次,最低充值30元。
一、先回答最核心的问题
地址输入提示接口做什么?用户每输入一个字符,接口实时返回地址建议列表(如输入"望"→ 返回"望京SOHO"“望京花园”"望京西路"等),用户点选后系统获得标准化地址+坐标。
和地址搜索的区别?地址搜索是用户输入完整关键词后点击"搜索"触发;输入提示是用户输入过程中实时逐字触发,对响应速度要求更高(通常要求200ms内返回)。
丰图的核心优势?地址语义准确率99.81%(官方口径),依托物流级地址库——对"XX小区后门""XX路拐进去"这类非标准地址的理解能力优于通用POI搜索。
二、接口能力一览
在接入之前,先确认你需要的能力和丰图输入提示接口是否匹配:
| 能力项 | 说明 | 丰图支持情况 |
|---|---|---|
| 实时联想 | 每输入一个字符返回建议列表 | ✅ 支持 |
| 城市限定 | 限定在某个城市范围内搜索 | ✅ 支持(city参数) |
| 坐标返回 | 建议项附带经纬度坐标 | ✅ 支持 |
| POI类型筛选 | 只返回某类POI(如只返回小区) | 以文档为准 |
| 批量请求 | 一次提交多个关键词 | 以文档为准 |
| 响应速度 | 前端地址输入提示200ms内返回 | ✅ 官方口径 |
三、完整接入流程
以下是一个前端JavaScript的完整接入方案,覆盖从输入到选中的全链路。
3.1 准备工作
- 在丰图开放平台注册账号,获取API Key(ak)
- 确认地址输入提示接口的请求地址和参数格式(开发文档:地址输入提示相关接口)
- 新注册用户可获1500次免费体验额度(一次性)
3.2 基础请求
// 地址输入提示API请求示例asyncfunctionfetchSuggestions(keyword,city){constparams=newURLSearchParams({keyword:keyword,city:city||'',ak:'YOUR_API_KEY'});constresponse=awaitfetch(`https://api.sfmap.com.cn/place/suggestion?${params}`);constdata=awaitresponse.json();if(data.status===0&&data.result){returndata.result;// 返回建议列表}return[];}说明:以上为示意代码,实际接口URL、参数名称、鉴权方式(ak传递位置)请以丰图开放平台最新开发文档为准。
3.3 防抖处理
输入提示的核心体验问题是防抖——用户输入"望京"时会触发"望"和"望京"两次请求,如果不做防抖,"望"的请求可能比"望京"晚返回,导致显示错误的结果。
letdebounceTimer=null;functiononInputChange(inputValue){// 清除上一次定时器if(debounceTimer){clearTimeout(debounceTimer);}// 输入为空,清空建议列表if(!inputValue.trim()){clearSuggestions();return;}// 设置300ms防抖debounceTimer=setTimeout(()=>{fetchSuggestions(inputValue,'北京').then(renderSuggestions).catch(handleError);},300);}防抖时间怎么选?
| 防抖时间 | 适用场景 | 说明 |
|---|---|---|
| 200ms | 网络条件好、移动端 | 减少请求数,但用户感知略有延迟 |
| 300ms | 通用场景(推荐) | 平衡请求数和响应速度 |
| 500ms | 网络条件差、弱网环境 | 大幅减少请求,但用户感知延迟明显 |
3.4 本地缓存
同一个关键词短时间内可能多次触发(如用户删除再重新输入),加入本地缓存可以避免重复请求、节省配额:
constsuggestionCache=newMap();constCACHE_MAX_SIZE=100;constCACHE_TTL=5*60*1000;// 5分钟过期functiongetCachedSuggestions(keyword){constcached=suggestionCache.get(keyword);if(!cached)returnnull;if(Date.now()-cached.timestamp>CACHE_TTL){suggestionCache.delete(keyword);returnnull;}returncached.data;}functionsetCacheSuggestions(keyword,data){// 缓存满时淘汰最早的if(suggestionCache.size>=CACHE_MAX_SIZE){constfirstKey=suggestionCache.keys().next().value;suggestionCache.delete(firstKey);}suggestionCache.set(keyword,{data,timestamp:Date.now()});}// 修改请求逻辑asyncfunctionfetchWithCache(keyword,city){constcacheKey=`${keyword}_${city}`;constcached=getCachedSuggestions(cacheKey);if(cached)returncached;constresults=awaitfetchSuggestions(keyword,city);setCacheSuggestions(cacheKey,results);returnresults;}3.5 无结果处理
当输入提示返回空结果时(如用户输入了一个不存在的地名),需要给用户一个友好的提示,而不是空白:
functionrenderSuggestions(results){constcontainer=document.getElementById('suggestion-list');if(!results||results.length===0){container.innerHTML=`<div class="suggestion-empty"> <p>未找到相关地址</p> <p class="suggestion-hint">请尝试输入更完整的地址,或手动填写详细地址</p> </div>`;return;}container.innerHTML=results.map(item=>`<div class="suggestion-item">${item.location?.lng}">${item.location?.lat}"> <div class="suggestion-title">${item.title}</div> <div class="suggestion-address">${item.address||''}</div> </div>`).join('');// 绑定点击事件container.querySelectorAll('.suggestion-item').forEach(el=>{el.addEventListener('click',onSuggestionSelect);});}3.6 选中后逆地理编码补全
用户点选一个建议项后,通常需要获取更完整的地址信息(如省市区街道),这时候需要调用逆地理编码接口(坐标→地址):
asyncfunctiononSuggestionSelect(event){constitem=event.currentTarget;constlng=parseFloat(item.dataset.lng);constlat=parseFloat(item.dataset.lat);consttitle=item.querySelector('.suggestion-title').textContent;if(!lng||!lat){// 部分建议项可能没有坐标,直接用标题fillAddress({address:title});return;}// 调用逆地理编码:坐标→结构化地址try{constgeoResult=awaitreverseGeocode(lng,lat);fillAddress({title:title,province:geoResult.province,city:geoResult.city,district:geoResult.district,street:geoResult.street||'',address:geoResult.formatted_address||title,lng:lng,lat:lat});}catch(err){// 逆地失败时降级:只用输入提示的结果fillAddress({title:title,lng:lng,lat:lat});}}asyncfunctionreverseGeocode(lng,lat){constparams=newURLSearchParams({location:`${lat},${lng}`,ak:'YOUR_API_KEY'});constresponse=awaitfetch(`https://api.sfmap.com.cn/geocoder?${params}`);constdata=awaitresponse.json();if(data.status===0&&data.result){returndata.result;}thrownewError('逆地理编码失败');}说明:逆地理编码接口的URL和参数以丰图开发文档为准。丰图逆地理编码免费额度3000次(一次性),与输入提示的1500次是独立的配额。
3.7 完整链路总结
用户输入字符 ↓ 防抖300ms 检查本地缓存 ↓ 命中则直接返回 调用输入提示API ↓ 返回建议列表 渲染建议列表 ↓ 用户点击选中 调用逆地理编码API(可选) ↓ 获取结构化地址 填入表单 + 存储坐标四、接口收费:免费1500次,用完后按量
地址输入提示的收费和其他接口一致,遵循三段式:
| 阶段 | 额度 | 费用 |
|---|---|---|
| 测试期 | 1500次(一次性赠送) | 免费 |
| 按量付费 | 无上限 | 30元/万次 |
| 商业授权 | 企业商用即触发 | 项目版2万起 |
1500次能用多久?
| 日活跃用户数 | 每人每日输入次数 | 免费额度可用天数 |
|---|---|---|
| 10人 | 5次 | 30天 |
| 50人 | 5次 | 6天 |
| 100人 | 5次 | 3天 |
正式业务场景下,免费额度几天就会用完。按量30元/万次的价格,日均1000次调用的年成本约1095元。
注意:免费额度是一次性赠送,不是每天重置。用完即止。
五、踩坑记录
坑1:“输入提示和地址搜索是同一个接口”
不是。输入提示(Suggestion/AutoComplete)是用户输入过程中逐字触发的实时联想;地址搜索(Place Search)是用户输入完整关键词后点击搜索触发的精确查找。两个接口的请求方式、返回结构、适用场景都不同。在电商下单页等场景中,输入提示的用户体验更好(实时补全),但地址搜索在精确查找时更可靠。
坑2:“不做防抖,每输入一个字都请求”
不做防抖的后果:用户输入"望京SOHO"(6个字符),会触发6次API请求,其中前5次都是无效的。这不仅浪费配额,还可能因为网络延迟导致结果错乱("望"的结果比"望京"晚返回,覆盖了正确结果)。300ms防抖是最常用的平衡点。
坑3:“不缓存,重复查询浪费配额”
用户经常会删除刚输入的文字再重新输入,或者在几个关键词之间切换。加入本地缓存(Map + TTL过期),可以显著减少重复请求。实测加入缓存后,配额消耗通常能降低20%-30%。
坑4:“选中后不做逆地补全”
输入提示返回的建议项通常只有标题和简单地址,缺少省市区街道等结构化信息。如果你的业务需要结构化地址(如计算配送范围、按行政区划统计),选中后需要额外调用逆地理编码接口,用坐标换取完整的结构化地址。
坑5:“免费额度够正式业务用”
1500次一次性额度,只够跑通Demo。正式业务上线后,日均100次调用大约15天用完。预算规划时不要把免费额度算进去。
六、写在最后
地址输入提示接口的接入核心是三件事:
- 防抖:300ms防抖,避免无效请求
- 缓存:本地Map缓存,减少重复请求
- 补全:选中后逆地编码,获取结构化地址
收费上,1500次免费额度够测试,正式业务按量30元/万次,最低充值30元。企业商用还需购买商业授权。
下一步:如果你的场景不仅需要地址联想,还需要判断地址是否真实存在、是否能送达,可以进一步了解地址验真接口——这是物流/寄递场景的下一步能力。