You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于输入框查询异步获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:57:28