javascript怎样发送网络请求_fetch API如何使用【教程】
技术百科
夜晨
发布时间:2026-01-27
浏览: 次 fetch 发 GET 请求需 await fetch() 后调用 await res.json();POST 要匹配 body 与 Content-Type;超时/取消需 AbortController;跨域问题源于预检失败或 CORS 响应头缺失。
fetch 基本用法:发个 GET 请求别漏掉 await 和 .json()
fetch 默认不自动解析响应体,直接 await fetch(url) 拿到的是一个 Response 对象,不是 JSON 数据。常见错误是忘了调用 .json() 或 .text(),结果打印出来是 [object Promise] 或控制台报错 TypeError: Failed to execute 'json' on 'Response': body stream is locked。
正确写法示例:
async function getData() {
const res = await fetch('/api/user');
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
const data = await res.json(); // 必须 await 这一步
r
eturn data;
}
-
fetch()返回 Promise,必须用await或.then()处理 -
res.ok判断 HTTP 状态是否在 200–299 范围,404、500不会自动 reject -
.json()本身也返回 Promise,不能省略await - 如果后端返回的是纯文本或 HTML,改用
res.text();二进制用res.arrayBuffer()
POST 请求怎么传数据?body 和 headers 别配错
fetch 发 POST 时,Content-Type 和 body 格式必须匹配,否则后端收不到字段。最常踩的坑是:传了 JSON.stringify(obj) 却没设 headers: {'Content-Type': 'application/json'},或者反过来,用 FormData 却写了 application/json。
常见组合:
// JSON 数据(推荐 API 场景)
fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'a@b.c', password: '123' })
});
// 表单数据(上传文件或兼容传统后端)
const form = new FormData();
form.append('file', fileInput.files[0]);
fetch('/upload', {
method: 'POST',
body: form // 此时不要设 Content-Type,浏览器会自动生成带 boundary 的 multipart
});
-
FormData实例直接当body,不要手动设Content-Type,否则会破坏 boundary -
JSON.stringify()后的字符串是string类型,不是对象,别漏掉这步 - GET 请求不能有
body,参数只能拼在 URL 后或用URLSearchParams
fetch 无法 abort 或 timeout?得靠 AbortController
fetch 本身不支持超时或手动取消,长时间 pending 会卡住 UI。原生方案是用 AbortController,但要注意:它只中断网络请求,不会自动清理 Promise,且 abort() 后再 await 会抛 AbortError。
function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
return fetch(url, { signal: controller.signal })
.finally(() => clearTimeout(id));
}
// 使用
fetchWithTimeout('/slow-api')
.then(r => r.json())
.catch(err => {
if (err.name === 'AbortError') console.log('请求超时');
});
-
signal选项必须显式传入fetch配置,否则无效 -
AbortController是一次性对象,每次请求都要新建实例 - 超时逻辑需自己用
setTimeout+clearTimeout配合,fetch 无内置 timeout 参数 - 某些旧版 Safari 不支持
AbortController,需检查兼容性或用 polyfill
跨域失败时,浏览器控制台只显示 "Failed to fetch"?先看预检和 CORS 响应头
fetch 遇到跨域且服务端未正确配置 CORS 时,控制台通常只报 TypeError: Failed to fetch,没有具体原因。这是因为浏览器在发出实际请求前会先发 OPTIONS 预检,如果预检失败(如缺少 Access-Control-Allow-Origin),整个请求就被拦在网关外,fetch 拿不到任何响应。
排查步骤:
- 打开 DevTools → Network → 找到对应请求 → 查看 Headers 标签页,确认响应头含
Access-Control-Allow-Origin: *或指定域名 - 如果有自定义 header(如
Authorization)或非简单方法(PUT、DELETE),必须确保服务端同时返回Access-Control-Allow-Headers和Access-Control-Allow-Methods -
前端加
credentials: 'include'时,后端Access-Control-Allow-Origin不能为*,必须写明确域名 - 本地开发常用代理绕过 CORS(如 Vite 的
server.proxy或 Webpack 的devServer.proxy),而非在代码里硬加mode: 'no-cors'(它禁用 JS 读响应,基本没用)
fetch 的行为很“干净”,但也因此把很多底层细节(比如预检、流锁、header 匹配)推给了开发者判断——真正难的不是调用,而是看清请求到底卡在哪一层。
# safari
# 浏览器
# app
# word
# js
# json
# javascript
# java
# String
# html
# 字符串
# access
# signal
# delete
# 前端
# Object
# include
# vite
# webpack
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎样彻底卸载自带应用_Win11彻底卸载
- Win11怎么开启远程桌面_Win11系统远程桌面
- Win11怎么设置鼠标宏_Win11鼠标按键自定义
- PHP主流架构怎么处理表单验证_规则与自定义【技巧
- Bpmn 2.0的XML文件怎么画流程图
- 如何使用Golang模拟请求超时_Golang c
- Mac的Time Machine怎么用_Mac系统
- 如何在 Go 结构体中正确初始化 map 字段
- 如何在同包不同文件中正确引用 Go 结构体
- 如何使用Golang实现文件追加操作_向已有文件追
- Python异步网络编程_aiohttp说明【指导
- mac怎么安装pip_MAC Python pip
- Win11怎么查看wifi信号强度_检测Windo
- 微信里的php文件怎么变mp4_微信接收php转m
- Drupal 中 HTML 链接被双重转义导致渲染
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- php与c语言在嵌入式中有何区别_对比两者在硬件控
- LINUX如何查看文件类型_Linux中file命
- PHP主流架构如何做单元测试_工具与流程【详解】
- Win11怎么关闭防火墙通知_屏蔽Win11安全中
- 使用类变量定义字符串常量时如何实现类型安全的 Li
- PythonFastAPI项目实战教程_API接口
- Go语言中正确反序列化多个同级XML元素为结构体切
- php怎么下载安装并配置环境变量_命令行调用PHP
- php中::能用于接口静态方法吗_接口静态方法调用
- MAC如何修改默认应用程序_MAC文件后缀关联设置
- Win11怎么查看显卡温度 Win11任务管理器查
- Python lxml的etree和Element
- Mac如何将HEIC图片格式转为JPG_Mac批量
- 如何减少Golang内存碎片化_Golang内存分
- 如何使用Golang匿名函数_快速定义临时函数逻辑
- php485返回空数组怎么回事_php485数据接
- Win11怎么设置DNS服务器_Windows11
- mac本地php环境如何开启curl_curl扩展
- php怎么下载安装后测试是否成功_简单脚本验证方法
- Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱
- Windows10如何更改桌面图标间距_Win10
- 如何用::实现单例模式_php静态方法与作用域操作
- 如何高效删除 NumPy 二维数组中所有元素相同的
- Win11如何暂停系统更新 Win11暂停更新最长
- Mac如何设置动态壁纸?(让桌面动起来)
- Win10任务栏天气和资讯怎么关闭 Win10禁用
- Windows10如何更改鼠标灵敏度_Win10鼠
- Win11怎么设置组合键快捷方式_Windows1
- Python集合操作技巧_高效去重解析【教程】
- c++ reinterpret_cast怎么用 c
- php订单日志怎么记录发货_php记录订单发货操作
- XSLT怎么生成动态的HTML属性名和标签名
- 如何使用Golang table-driven f
- windows 10专注助手怎么关闭_window


QQ客服