2026 字
10 分钟
网络请求 fetch 完整教程(请求后端数据)

网络请求 fetch 完整教程(请求后端数据)#

前两篇我们学了异步编程。为什么要学它?因为真正的项目里,数据几乎都在”服务器”上,不在你的页面里。页面要向服务器”要数据”,这个动作就是网络请求

这一篇教你怎么用 fetch 发出请求、拿到数据、处理错误,并且会拿一个真实的公开 API 来实战。


一、先理解:网页和服务器怎么对话?#

你的浏览器(前端)向服务器(后端)发出请求,服务器返回数据,浏览器再把数据显示出来。就像你去餐厅:你点菜(请求),厨师做好端上来(响应)。

这个”点菜-上菜”的对话,用的协议叫 HTTP。其中最常见的两种”点菜方式”:

方法作用比喻
GET获取数据看菜单,不改变任何东西
POST提交数据下单,把新东西交给服务器

比如:

  • 打开一个新闻网站 → 浏览器发 GET 请求,服务器返回新闻列表
  • 你登录账号 → 浏览器发 POST 请求,把用户名密码交给服务器

二、fetch 的基本用法(GET 请求)#

fetch 是浏览器内置的函数,专门用来发网络请求。最简单的用法:

fetch("https://example.com/api/data")
.then(response => response.json())
.then(data => {
console.log(data);
});

一步步拆解#

// 1. 发出请求,fetch 返回一个 Promise
let promise = fetch("https://example.com/api/data");
// 2. 等响应:response 是一个"响应对象",要先调用 .json() 把数据解析出来
promise
.then(response => response.json()) // .json() 也返回 Promise
.then(data => { // 这里的 data 才是真正的数据
console.log(data);
});

为什么有两次 then? 第一次拿到的是”响应信封”(response),信封里装着数据,要用 .json() 拆开;.json() 本身也是异步的(要读完整数据),所以又要等一次。

用 async/await 写(推荐,清晰得多)#

async function getData() {
let response = await fetch("https://example.com/api/data");
let data = await response.json();
console.log(data);
}
getData();

和上面的 then 版本完全等价,但读起来像同步代码,推荐以后都用这种写法。


三、实战:请求一个真实的公开 API#

我们用一个完全免费、无需密钥的公开 API:JSONPlaceholder,它专门给新手练手,返回假数据。

async function 获取文章() {
let response = await fetch("https://jsonplaceholder.typicode.com/posts");
let posts = await response.json();
console.log(posts);
}
获取文章();

打开浏览器控制台运行,几秒后你会看到一长串数据——每篇”文章”长这样:

{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati",
"body": "quia et suscipit..."
}

你已经成功从服务器拿到数据了! 这就是全栈开发中”前端请求数据”的核心一步。

把数据显示到页面上#

拿到的数据要展示给用户,得操作 DOM:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文章列表</title>
</head>
<body>
<h1>文章列表</h1>
<ul id="postList"></ul>
<script>
async function 加载文章() {
let response = await fetch("https://jsonplaceholder.typicode.com/posts");
let posts = await response.json();
let list = document.getElementById("postList");
for (let post of posts.slice(0, 5)) { // 只显示前 5 篇
let li = document.createElement("li");
li.textContent = post.title;
list.appendChild(li);
}
}
加载文章();
</script>
</body>
</html>

用浏览器打开,等一两秒,页面上就会出现 5 条文章标题。


四、POST 请求:向服务器提交数据#

GET 是”要数据”,POST 是”交数据”。提交登录、发评论、注册账号都用 POST。

async function 提交数据() {
let response = await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST", // 指定方法
headers: {
"Content-Type": "application/json" // 告诉服务器:我发的是 JSON
},
body: JSON.stringify({ // 把 JS 对象转成 JSON 字符串
title: "我的新文章",
body: "这是我的内容",
userId: 1
})
});
let data = await response.json();
console.log(data);
}
提交数据();

两个关键点:

  1. JSON.stringify(对象):把 JS 对象转成字符串。因为网络传输的只能是一串文字,所以要”序列化”
  2. headers:告诉服务器发送内容的格式。JSON 就写 "Content-Type": "application/json"

服务器返回的数据里,会包含新创建数据的 id,表示创建成功。


五、错误处理:网络请求一定会出错#

请求网络可能遇到各种问题:断网、服务器挂了、接口地址写错、返回的不是 JSON……

两种错误要区分#

第一种:网络层错误(根本没连上)——fetch 会直接失败,进 catch:

async function 请求() {
try {
let response = await fetch("https://不存在的地址.com");
let data = await response.json();
console.log(data);
} catch (error) {
console.log("请求失败:", error);
}
}

第二种:HTTP 错误(连上了,但服务器返回了错误状态)——比如 404(找不到)、500(服务器出错)。注意:fetch 对这类错误不会进 catch,response 还是能拿到,只是 response.ok 是 false:

async function 请求() {
let response = await fetch("https://jsonplaceholder.typicode.com/posts/999999");
console.log(response.ok); // false(这个 id 不存在,返回 404)
if (!response.ok) {
console.log("出错了,状态码:", response.status); // 404
return;
}
let data = await response.json();
console.log(data);
}

正确的完整写法: 两者都要处理

async function 安全请求(url) {
try {
let response = await fetch(url);
if (!response.ok) {
throw new Error(`请求失败:${response.status}`); // 主动抛错
}
let data = await response.json();
return data;
} catch (error) {
console.log("出错了:", error.message);
return null;
}
}
安全请求("https://jsonplaceholder.typicode.com/posts/1");

throw new Error(...) 会主动制造一个错误,让后面的 catch 接住——这是”把 HTTP 错误统一成异常处理”的常用手法。


六、完整实战:带加载状态的天气查询页#

把前面所有知识串起来:输入城市名 → 请求天气 API → 显示结果,并处理”加载中”和”出错”。

我们用 Open-Meteo 的免费天气 API(无需密钥)。它需要经纬度,所以先用另一个免费接口 geocoding-api 把城市名转成经纬度。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>天气查询</title>
<style>
body { font-family: sans-serif; max-width: 400px; margin: 40px auto; }
#result { margin-top: 20px; padding: 20px; background: #f0f4ff; border-radius: 10px; }
.loading { color: #888; }
.error { color: red; }
</style>
</head>
<body>
<h1>🌤 天气查询</h1>
<input id="city" placeholder="输入城市名,如 beijing">
<button id="search">查询</button>
<div id="result">输入城市后点查询</div>
<script>
let btn = document.getElementById("search");
let input = document.getElementById("city");
let result = document.getElementById("result");
btn.addEventListener("click", async () => {
let city = input.value.trim();
if (!city) return;
result.textContent = "加载中...";
result.className = "loading";
try {
// 第一步:城市名 → 经纬度
let geoRes = await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${city}&count=1`);
let geoData = await geoRes.json();
let place = geoData.results && geoData.results[0];
if (!place) {
throw new Error("找不到这个城市");
}
// 第二步:用经纬度查天气
let lat = place.latitude;
let lon = place.longitude;
let weatherRes = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}&current_weather=true`);
let weather = await weatherRes.json();
// 第三步:显示结果
let temp = weather.current_weather.temperature;
let wind = weather.current_weather.windspeed;
result.className = "";
result.innerHTML = `
<h2>${place.name}</h2>
<p>温度:${temp} °C</p>
<p>风速:${wind} km/h</p>
`;
} catch (error) {
result.className = "error";
result.textContent = "查询失败:" + error.message;
}
});
</script>
</body>
</html>

这段代码演示了真实项目的完整流程:

  1. 用户点击 → 先显示”加载中…”
  2. 两次 fetch:先查经纬度,再查天气(第二次请求依赖第一次的结果,用 await 按顺序等)
  3. 成功 → 把数据显示到页面(用模板字符串拼 HTML)
  4. 失败 → 显示错误信息

保存成 HTML 用浏览器打开,输入 beijing 点查询,等一两秒就能看到北京的温度和风速。


七、几个实战小技巧#

1. 请求参数拼接#

GET 请求的参数拼在 URL 后面,用 ?&

// https://api.example.com/search?keyword=手机&page=2&size=10
let url = `https://api.example.com/search?keyword=${keyword}&page=2&size=10`;

2. 设置超时(防止一直转圈)#

AbortController 让请求最多等 10 秒:

let controller = new AbortController();
let timer = setTimeout(() => controller.abort(), 10000);
try {
let response = await fetch(url, { signal: controller.signal });
// ...
} catch (error) {
console.log("请求超时或失败");
} finally {
clearTimeout(timer);
}

3. 请求带 token(登录后的常见需求)#

在 headers 里加 Authorization 字段:

let response = await fetch(url, {
headers: {
"Authorization": "Bearer 你的token"
}
});

八、总结#

这一篇的关键收获:

  • HTTP 基础:GET 获取数据,POST 提交数据
  • fetch 基本用法fetch(url)response.json() → 数据
  • async/await 版本:清晰、推荐、主流
  • POST 请求:method、headers、JSON.stringify 序列化
  • 两类错误:网络错误(catch)、HTTP 错误(response.ok 检查)
  • 实战:文章列表、天气查询,都是真实项目的标准写法

学会了 fetch,你的网页就真正”活”起来了——能向服务器要数据、交数据。下一篇我们回头补HTML 和 CSS,把页面做得更漂亮。

网络请求 fetch 完整教程(请求后端数据)
https://021028.xyz/posts/default/69/
作者
021028
发布于
2026-08-11
许可协议
CC BY-NC-SA 4.0