4.1 调用第三方 API
这一节教你用别人已经做好的 API,就像去餐厅点菜一样简单。
学完这节你会:
- 理解什么是 API(不用记那些专业术语)
- 会调用天气 API 显示实时天气
- 会调用 DeepSeek API 做一个 AI 聊天功能
- 知道怎么安全地管理 API 密钥
什么是 API?用餐厅类比理解
API 就像餐厅的服务员:
你(前端):「我要一份宫保鸡丁」 → 服务员(API)把单子交给厨房 → 厨房(后端/数据库)做好了 → 服务员把菜端给你
你不用进厨房,只需要:
- 知道怎么点菜(调用 API)
- 等着接菜(接收数据)
第三方 API vs 自己写的 API
| 类型 | 比喻 | 例子 |
|---|---|---|
| 第三方 API | 去别人餐厅吃饭 | 天气 API、DeepSeek API、地图 API |
| 自己写的 API | 自己开餐厅 | 你自己的数据库操作接口 |
这一节先学第一种 - 用别人的,最简单!
实战 1:调用天气 API
我们用免费的天气 API 来做第一个例子。
步骤 1:获取 API 密钥
- 访问 WeatherAPI.com
- 注册免费账号
- 获取你的 API Key(类似
sk-a1b2c3d4e5f6...)
API Key 就像你家钥匙,别告诉别人! 待会儿我们会教你怎么安全存储。
步骤 2:测试 API 调用
打开浏览器,访问这个网址(把 YOUR_API_KEY 替换成你的密钥):
https://api.weatherapi.com/v1/current.json?key=YOUR_API_KEY&q=Beijing你应该能看到一堆 JSON 数据,类似:
什么是 JSON? JSON(JavaScript Object Notation)是一种数据格式,用来在网络上传输数据。它用大括号
{}表示对象,方括号[]表示数组,冒号:分隔键和值。几乎所有 API 返回的数据都是 JSON 格式。
{
"location": {
"name": "Beijing",
"country": "China"
},
"current": {
"temp_c": 15.0,
"condition": {
"text": "Sunny"
}
}
}恭喜!你已经成功调用了一个真实的 API!
步骤 3:在 Next.js 项目中调用
创建一个新页面 app/weather/page.tsx:
代码解读:
'use client'告诉 Next.js 这是客户端组件(需要浏览器交互)。useState是 React 的「状态钩子」,用来存储会变化的数据(城市名、天气数据、加载状态)。async/await是处理异步操作的语法,让你可以「等待」API 返回数据。
'use client'
import { useState } from 'react'
export default function WeatherPage() {
const [city, setCity] = useState('Beijing')
const [weather, setWeather] = useState(null)
const [loading, setLoading] = useState(false)
const getWeather = async () => {
setLoading(true)
try {
// 注意:这里先硬编码,下一步我们会改进
const API_KEY = 'YOUR_API_KEY' // ⚠️ 先别这样做!
const res = await fetch(
`https://api.weatherapi.com/v1/current.json?key=${API_KEY}&q=${city}`
)
const data = await res.json()
setWeather(data)
} catch (error) {
console.error('获取天气失败', error)
}
setLoading(false)
}
return (
<div className="p-8">
<h1 className="text-2xl font-bold mb-4">天气查询</h1>
<input
type="text"
value={city}
onChange={(e) => setCity(e.target.value)}
placeholder="输入城市名"
className="border p-2 mr-2"
/>
<button
onClick={getWeather}
className="bg-blue-500 text-white px-4 py-2 rounded"
>
查询天气
</button>
{loading && <p className="mt-4">加载中...</p>}
{weather && (
<div className="mt-4 p-4 border rounded">
<h2 className="text-xl">{weather.location.name}</h2>
<p>温度:{weather.current.temp_c}°C</p>
<p>天气:{weather.current.condition.text}</p>
</div>
)}
</div>
)
}步骤 4:安全管理 API 密钥 ⭐
问题:上面的代码把 API Key 直接写在代码里,这样:
- ❌ Key 会被任何人看到(如果你的代码开源)
- ❌ 部署到 GitHub 会泄露
正确做法:用环境变量
- 在项目根目录创建
.env.local文件:
# .env.local
NEXT_PUBLIC_WEATHER_API_KEY=你的真实API密钥- 修改代码:
const API_KEY = process.env.NEXT_PUBLIC_WEATHER_API_KEY- 确保
.env.local在.gitignore里(Next.js 默认已包含)
为什么要加 NEXT_PUBLIC_ 前缀?
Next.js 规定:
NEXT_PUBLIC_开头的变量可以在浏览器(客户端)使用- 没有这个前缀的只能在服务端使用
因为我们在 'use client' 组件里调用,所以需要加前缀。
步骤 5:部署时配置环境变量
如果你用 Vercel 部署:
- 打开项目设置 → Environment Variables
- 添加
NEXT_PUBLIC_WEATHER_API_KEY,值填你的 API Key - 重新部署
实战 2:调用 DeepSeek API(AI 聊天)
现在我们来做一个更酷的 - AI 聊天功能!
步骤 1:获取 DeepSeek API Key
- 访问 DeepSeek 官网
- 注册并获取 API Key
- 查看API 文档
步骤 2:创建 API Route(后端接口)
为什么这次要用 API Route?
DeepSeek API Key 很敏感,不能在前端暴露! 所以我们要:
- 前端 → 调用自己的 API Route
- API Route → 调用 DeepSeek API(Key 在服务端,安全)
创建 app/api/chat/route.ts:
什么是 API Route? Next.js 的 API Route 让你在同一个项目里写后端代码。
app/api/文件夹里的文件会变成后端接口,比如app/api/chat/route.ts会变成/api/chat这个接口地址。前端调用它,它再调用外部 API,这样敏感信息就不会暴露给用户。
import { NextRequest, NextResponse } from 'next/server'
export async function POST(request: NextRequest) {
try {
const { message } = await request.json()
// 调用 DeepSeek API
const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.DEEPSEEK_API_KEY}` // 服务端环境变量,不需要 NEXT_PUBLIC_
},
body: JSON.stringify({
model: 'deepseek-chat',
messages: [
{ role: 'user', content: message }
]
})
})
const data = await response.json()
return NextResponse.json({
reply: data.choices[0].message.content
})
} catch (error) {
return NextResponse.json(
{ error: '请求失败' },
{ status: 500 }
)
}
}步骤 3:创建前端页面
创建 app/chat/page.tsx:
'use client'
import { useState } from 'react'
export default function ChatPage() {
const [messages, setMessages] = useState([])
const [input, setInput] = useState('')
const [loading, setLoading] = useState(false)
const sendMessage = async () => {
if (!input.trim()) return
const userMessage = { role: 'user', content: input }
setMessages(prev => [...prev, userMessage])
setInput('')
setLoading(true)
try {
// 调用自己的 API Route
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: input })
})
const data = await res.json()
setMessages(prev => [...prev, {
role: 'assistant',
content: data.reply
}])
} catch (error) {
console.error('发送失败', error)
}
setLoading(false)
}
return (
<div className="max-w-2xl mx-auto p-8">
<h1 className="text-2xl font-bold mb-4">AI 聊天助手</h1>
<div className="border rounded p-4 h-96 overflow-y-auto mb-4">
{messages.map((msg, i) => (
<div key={i} className={`mb-2 ${msg.role === 'user' ? 'text-right' : 'text-left'}`}>
<span className={`inline-block p-2 rounded ${
msg.role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-200'
}`}>
{msg.content}
</span>
</div>
))}
{loading && <p className="text-gray-500">AI 正在思考...</p>}
</div>
<div className="flex gap-2">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
placeholder="输入消息..."
className="flex-1 border p-2 rounded"
/>
<button
onClick={sendMessage}
disabled={loading}
className="bg-blue-500 text-white px-4 py-2 rounded disabled:opacity-50"
>
发送
</button>
</div>
</div>
)
}步骤 4:配置环境变量
在 .env.local 添加:
DEEPSEEK_API_KEY=你的DeepSeek密钥注意这次不需要 NEXT_PUBLIC_ 前缀,因为只在服务端使用!
错误处理技巧
调用 API 时经常会出问题,学会处理错误很重要:
常见错误和解决方法:
-
401 Unauthorized - API Key 错误
检查 .env.local 里的 Key 是否正确 -
429 Too Many Requests - 请求太频繁
等几分钟再试,或升级 API 套餐 -
Network Error - 网络问题
检查网络连接,或 API 服务器是否正常 -
CORS Error - 跨域问题
用 API Route 做中转(就像 DeepSeek 例子)
什么是跨域(CORS)? 浏览器出于安全考虑,默认禁止网页向不同域名发请求。比如你的网站是
example.com,直接调用api.deepseek.com就会被拦截。解决方法是用自己的后端做「中转站」:前端 → 自己的 API Route → 第三方 API。
推荐的错误处理模板:
try {
const res = await fetch(apiUrl)
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`)
}
const data = await res.json()
return data
} catch (error) {
console.error('API 调用失败:', error)
// 给用户友好的提示
alert('请求失败,请稍后重试')
}环境变量管理总结
记住这个规则:
| 使用场景 | 变量名格式 | 存储位置 | 能否在客户端用 |
|---|---|---|---|
| 客户端调用 API | NEXT_PUBLIC_XXX | .env.local | ✅ 能 |
| 服务端调用 API | XXX(不加前缀) | .env.local | ❌ 不能 |
最佳实践:
- ✅ 敏感 Key(DeepSeek):用 API Route 中转
- ✅ 公开 Key(地图 API):可以直接用
NEXT_PUBLIC_ - ✅ 永远不要把
.env.local提交到 Git - ✅ 部署时记得配置 Vercel 环境变量
快速实践建议
从最简单的开始,不要一次做太复杂:
Day 1: 天气 API
复制上面的天气代码,跑通
Day 2: 环境变量
学会用 .env.local 管理密钥
Day 3: DeepSeek API
做一个简单的 AI 聊天
Day 4: 加功能
给天气 App 加个城市列表,或给聊天加个历史记录
新手常见卡点:
-
忘记重启开发服务器 修改
.env.local后要重启pnpm run dev -
环境变量拼写错误
NEXT_PUBLIC_WEATHER_API_KEY少个字母就找不到 -
混淆客户端和服务端 客户端组件(‘use client’)只能用
NEXT_PUBLIC_变量
下一节:4.2 数据库与 CRUD 操作 - 学会存储和管理自己的数据