RedwoodJS项目实战:集成第三方天气API开发天气应用

RedwoodJS项目实战:集成第三方天气API开发天气应用

redwood The App Framework for Startups redwood 项目地址: https://gitcode.com/gh_mirrors/re/redwood

本文将详细介绍如何在RedwoodJS项目中集成第三方API(以OpenWeather天气API为例),通过两种不同方式实现天气查询功能:客户端直接调用和服务端代理调用。

项目概述

我们将开发一个简单的天气查询应用,用户输入美国邮编后,系统会显示该地区的当前天气情况。项目将演示两种技术方案:

  1. 客户端直接调用OpenWeather API
  2. 通过Redwood服务端代理调用API

准备工作

获取API密钥

首先需要注册OpenWeather账号并获取API密钥:

  1. 访问OpenWeather官网创建免费账号
  2. 验证邮箱后,在API Keys标签页获取默认密钥
  3. 注意:密钥可能需要30分钟激活

了解API响应

OpenWeather API返回JSON格式数据,包含以下关键信息:

  • name:城市名称
  • main.temp:温度(开尔文)
  • weather[0].main:天气状况描述
  • weather[0].icon:天气图标代码

温度需要从开尔文转换为华氏度:华氏度 = (开尔文 - 273.15) × 9/5 + 32

方案一:客户端直接调用API

实现步骤

  1. 创建Redwood项目:

    yarn create redwood-app weatherstation
    cd weatherstation
    yarn rw dev
    
  2. 生成首页:

    yarn rw generate page home /
    
  3. 构建表单组件:

    import { Form, TextField, Submit } from '@redwoodjs/forms'
    import { useState } from 'react'
    
    const HomePage = () => {
      const [weather, setWeather] = useState()
    
      const onSubmit = (data) => {
        fetch(`https://api.openweathermap.org/data/2.5/weather?zip=${data.zip},us&appid=YOUR_API_KEY`)
          .then((response) => response.json())
          .then((json) => setWeather(json))
      }
    
      const temp = () => Math.round(((weather.main.temp - 273.15) * 9) / 5 + 32)
      const condition = () => weather.weather[0].main
      const icon = () => `http://openweathermap.org/img/wn/${weather.weather[0].icon}@2x.png`
    
      return (
        <>
          <Form onSubmit={onSubmit}>
            <TextField
              name="zip"
              placeholder="Zip code"
              maxLength="5"
              validation={{ required: true, pattern: /^\d{5}$/ }}
            />
            <Submit>Go</Submit>
          </Form>
          {weather && (
            <section>
              <h1>{weather.name}</h1>
              <h2>
                <img src={icon()} style={{ maxWidth: '2rem' }} />
                <span>{temp()}°F and {condition()}</span>
              </h2>
            </section>
          )}
        </>
      )
    }
    

方案优缺点分析

优点

  • 架构简单,无需服务端开发
  • 网络请求次数最少(直接调用)
  • 响应速度快

缺点

  • API密钥暴露在客户端,存在安全风险
  • 无法实施请求频率限制
  • 受CORS限制

方案二:服务端代理调用API

实现步骤

  1. 定义GraphQL Schema:

    // api/src/graphql/weather.sdl.js
    export const schema = gql`
      type Weather {
        zip: String!
        city: String!
        conditions: String!
        temp: Int!
        icon: String!
      }
    
      type Query {
        getWeather(zip: String!): Weather! @skipAuth
      }
    `
    
  2. 创建天气服务:

    // api/src/services/weather/weather.js
    import { fetch } from '@whatwg-node/fetch'
    
    export const getWeather = async ({ zip }) => {
      const response = await fetch(
        `http://api.openweathermap.org/data/2.5/weather?zip=${zip},US&appid=YOUR_API_KEY`
      )
      const json = await response.json()
    
      return {
        zip,
        city: json.name,
        conditions: json.weather[0].main,
        temp: Math.round(((json.main.temp - 273.15) * 9) / 5 + 32),
        icon: `http://openweathermap.org/img/wn/${json.weather[0].icon}@2x.png`,
      }
    }
    
  3. 创建天气查询Cell:

    yarn rw generate cell weather
    
  4. 实现天气Cell组件:

    // web/src/components/WeatherCell/WeatherCell.js
    export const QUERY = gql`
      query GetWeatherQuery($zip: String!) {
        weather: getWeather(zip: $zip) {
          zip
          city
          conditions
          temp
          icon
        }
      }
    `
    
    export const Success = ({ weather }) => (
      <section>
        <h1>{weather.city}</h1>
        <h2>
          <img src={weather.icon} style={{ maxWidth: '2rem' }} />
          <span>{weather.temp}°F and {weather.conditions}</span>
        </h2>
      </section>
    )
    
  5. 在首页集成天气Cell:

    // web/src/pages/HomePage/HomePage.js
    import { Form, TextField, Submit } from '@redwoodjs/forms'
    import { useState } from 'react'
    import WeatherCell from 'src/components/WeatherCell'
    
    const HomePage = () => {
      const [zip, setZip] = useState()
    
      const onSubmit = (data) => setZip(data.zip)
    
      return (
        <>
          <Form onSubmit={onSubmit}>
            <TextField
              name="zip"
              placeholder="Zip code"
              maxLength="5"
              validation={{ required: true, pattern: /^\d{5}$/ }}
            />
            <Submit>Go</Submit>
          </Form>
          {zip && <WeatherCell zip={zip} />}
        </>
      )
    }
    

方案优缺点分析

优点

  • API密钥安全,不会暴露给客户端
  • 可在服务端实现请求频率限制
  • 数据预处理(如温度转换)在服务端完成
  • 不受CORS限制

缺点

  • 需要额外开发服务端代码
  • 网络请求次数增加(客户端→服务端→API)

错误处理建议

对于服务端方案,建议添加错误处理逻辑:

export const getWeather = async ({ zip }) => {
  try {
    const response = await fetch(`http://api...`)
    if (!response.ok) throw new Error('API请求失败')
    
    const json = await response.json()
    if (json.cod !== 200) throw new Error(json.message || '无效的邮编')

    return {
      // 正常返回数据
    }
  } catch (error) {
    throw new Error(`获取天气数据失败: ${error.message}`)
  }
}

总结

本文通过RedwoodJS项目实战,演示了两种集成第三方API的方案。对于简单项目或内部工具,客户端直接调用更为便捷;而对于生产环境应用,服务端代理方案提供了更好的安全性和扩展性。开发者应根据项目实际需求选择合适的技术方案。

RedwoodJS的GraphQL和Cells架构使得服务端代理方案的实现变得异常简单,同时保持了代码的整洁性和可维护性。这种模式也适用于集成其他类型的第三方API服务。

redwood The App Framework for Startups redwood 项目地址: https://gitcode.com/gh_mirrors/re/redwood

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

井彬靖Harlan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值