如何基于输入框查询异步获取API数据?天气APP优化方案
解决天气APP中仅在获取城市名后调用API的最佳实践方案
嘿,我来帮你搞定这个问题,咱们按照前端最佳实践一步步调整你的代码,确保只有拿到有效城市名后才发起天气API请求:
先梳理你现有代码的几个核心问题
- 第一个版本里监听了input的
submit事件,但input元素本身不会触发这个事件,应该绑定到form上 - 没有对城市名做非空校验,导致空值也会发起无效请求
- 第二个版本错误地用了POST请求调用OpenWeatherMap的API,该接口实际需要GET请求
- 全局变量
cityName容易和实际输入值不一致,应该在提交时直接从表单获取最新值 - 缺少错误处理,async/await没有配合try/catch处理网络或API错误
修正后的完整实现代码
HTML部分(保持结构,仅微调提示)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>My cool weather app</title> <link href="https://fonts.googleapis.com/css?family=Raleway&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" href="index.css"> </head> <body> <main> <div class="search-container"> <div class="search-bar"> <form class="weatherdata-form"> <i class="fa fa-search fa-3x" id="icon"></i> <input type="text" class="search-placeholder" placeholder="Type city to find weather..." name="city-name" required/> <!-- 可以保留提交按钮,提升可用性,也可以用回车提交 --> <button type="submit" style="display:none;">Search Weather</button> </form> </div> <!-- 用来展示错误提示或天气结果 --> <div id="weather-result"></div> </div> </main> <script src="index.js"></script> </body> </html>
JavaScript部分(核心修正)
'use strict'; (function() { const inputEl = document.querySelector(".search-placeholder"); const formEl = document.querySelector('form.weatherdata-form'); const resultEl = document.getElementById('weather-result'); const API_KEY = '2489ed561dc99d173a2f394574bc107e'; // 防抖函数:处理输入时的placeholder更新(不影响提交逻辑) const debounce = (func, wait, immediate) => { let timeout; return function() { const context = this; const args = arguments; const later = function() { timeout = null; if (!immediate) func.apply(context, args); }; const callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; // 输入实时更新placeholder(防抖优化) const handleSearchText = debounce((e) => { const inputValue = e.target.value.trim(); if (inputValue) { inputEl.placeholder = inputValue; } else { inputEl.placeholder = "Type city to find weather..."; } }, 250); inputEl.addEventListener("keyup", handleSearchText); // 核心:获取天气数据的async函数,带校验和错误处理 async function getWeatherData(event) { // 第一步:阻止表单默认提交行为(必须最先做) event.preventDefault(); // 第二步:获取并校验城市名 const cityName = inputEl.value.trim(); if (!cityName) { resultEl.textContent = "请输入有效的城市名称!"; resultEl.style.color = "red"; return; } // 第三步:发起API请求(用encodeURIComponent处理特殊字符) try { resultEl.textContent = "正在获取天气数据..."; resultEl.style.color = "black"; const url = `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(cityName)}&appid=${API_KEY}&units=metric`; const response = await fetch(url); // 处理API返回的错误状态(比如城市不存在) if (!response.ok) { throw new Error(`请求失败:${response.statusText}`); } const weatherData = await response.json(); // 渲染天气结果(示例) resultEl.innerHTML = ` <h3>${weatherData.name} 的天气</h3> <p>温度:${weatherData.main.temp} ℃</p> <p>天气:${weatherData.weather[0].description}</p> `; } catch (error) { // 捕获网络错误或API错误 resultEl.textContent = `获取天气失败:${error.message}`; resultEl.style.color = "red"; } } // 绑定表单提交事件(正确的触发时机) formEl.addEventListener('submit', getWeatherData); })();
关键最佳实践说明
- 表单事件绑定:始终监听form的
submit事件,而不是input的,这样无论是点击提交按钮还是按回车,都能触发请求 - 前置校验:在发起请求前必须校验输入值,
trim()后判断是否为空,避免无效请求 - 避免全局状态依赖:提交时直接从input元素获取最新值,不用全局变量存储,防止状态不一致
- URL编码:用
encodeURIComponent()处理城市名,避免空格、特殊字符导致URL无效 - 错误处理:用
try/catch包裹async/await代码,同时检查response.ok处理API返回的错误状态 - 用户反馈:在请求过程中、成功、失败时都给用户明确的反馈,提升体验
内容的提问来源于stack exchange,提问作者theusual
相关产品推荐
相关产品推荐

