你是否曾在深夜被CORS错误折磨得抓狂?明明代码写得“完美无缺”,浏览器却弹出“Access-Control-Allow-Origin”报错,让你怀疑人生?作为混迹前端圈10年的老司机,我曾被这个问题坑得差点删库跑路。今天,我要彻底撕开Fetch API的“遮羞布”——那个被无数人忽略的mode属性。它不仅是跨域请求的“开关”,更是隐藏在代码深处的“定时炸弹”!90%的开发者用错它,导致项目上线后翻车。别急,看完这篇,你也能秒变跨域高手!
一、什么是mode属性?它为何如此重要?
在Fetch API中,mode属性是控制跨域请求行为的核心开关。它决定了浏览器如何处理请求的源(Origin)问题——简单说,就是“能不能跨域访问数据”。
为什么它被忽视? 因为默认值是cors(很多人不知道),而开发者往往直接写fetch(url),忽略了这个隐藏参数。结果?跨域请求失败时,你只会看到一堆报错,却找不到根源!
✅ 核心结论:
mode不是“可选参数”,而是跨域请求的“生死线”。用错它,你的API请求直接变“哑巴”。
二、mode的三种值详解:从“同源”到“跨域”的生死抉择
Fetch API的mode属性只有三个合法值,每个值背后都是CORS协议的“血泪史”。下面用真实案例拆解,拒绝教科书式废话!
1️⃣ same-origin:同源请求的“铁律”
- 作用:严格禁止跨域!请求必须和当前页面同源(协议+域名+端口完全一致)。
- 适用场景:访问自身服务器API(如
/api/users)。 - 错误示范:
// 当前页面是 https://example.com fetch('https://api.example.com/data', { mode: 'same-origin' }) .then(res => res.json()) .catch(err => console.error('❌ 跨域失败!', err)); // 一定会报错! - 为什么? 浏览器直接拦截:
Access to fetch at 'https://api.example.com/data' from origin 'https://example.com' has been blocked by CORS policy: Same-origin policy. - 正确用法:
// 仅限同源请求(如访问当前域名下的API) fetch('/api/data', { mode: 'same-origin' }); // ✅ 安全可靠
2️⃣ no-cors:跨域的“假朋友”(最易踩坑!)
- 作用:允许跨域请求,但响应是“不透明”的(Opaque)!你只能知道请求成功与否,无法读取响应内容(如
.text()、.json()会报错)。 - 适用场景:只读外部资源(如加载CDN图片、第三方脚本),绝不能用于获取数据!
- 真实案例:
// 加载外部图片(安全!) fetch('https://cdn.example.com/logo.png', { mode: 'no-cors' }) .then(res => { // ✅ 可以用res.url()获取URL,但不能读取内容 document.getElementById('img').src = res.url(); }); // ❌ 试图读取JSON(必报错!) fetch('https://api.example.com/data', { mode: 'no-cors' }) .then(res => res.json()) // ❌ 报错:TypeError: Failed to execute 'json' on 'Response': body is not loaded .catch(console.error); - 关键真相:
no-cors本质是“欺骗浏览器”——它告诉浏览器“我只想请求,不读数据”。但如果你试图读取响应,浏览器直接封杀!90%的踩坑事故源于此。
3️⃣ cors:跨域的“正道”(推荐用法!)
- 作用:标准跨域请求,需服务器配合设置CORS头(如
Access-Control-Allow-Origin),响应可正常读取。 - 适用场景:绝大多数跨域API调用(如调用第三方服务)。
- 正确实践:
// 1. 前端:设置mode: 'cors' fetch('https://api.example.com/data', { mode: 'cors' }) .then(res => res.json()) .then(data => console.log('✅ 数据成功获取', data)); // 2. 服务器必须配置CORS头(关键!) // 例如Node.js Express: app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://your-frontend.com'); res.header('Access-Control-Allow-Methods', 'GET, POST'); next(); }); - 为什么推荐它? 它是CORS协议的官方标准,响应可安全读取。除非你有特殊需求(如加载外部图片),否则永远用
cors!
三、实战避坑指南:这些错误我亲手踩过
| 错误场景 | 问题根源 | 正确解法 |
|---|---|---|
用no-cors读取JSON数据 | 响应是Opaque,无法解析 | 改用cors + 服务器配置CORS |
忽略mode直接写fetch | 默认cors,但服务器没配CORS | 检查服务器CORS头或改no-cors |
在same-origin跨域请求 | 强制同源,跨域直接被拦截 | 确认请求URL是同源的 |
💡 血泪教训:我曾在一个项目中用
no-cors请求用户数据,结果上线后数据全空。排查3小时才发现——no-cors不能读取响应!后来重写为cors,加上服务器CORS头,问题秒解。
四、进阶思考:如何优雅解决跨域问题?
- 优先用
cors+服务器配置:这是最安全、最标准的方案。别再用no-cors当“万能钥匙”! - 开发阶段用Proxy:用Webpack DevServer或Node.js代理,绕过浏览器CORS限制(无需改服务器)。
// webpack.dev.js devServer: { proxy: { '/api': 'http://api.example.com' } } - 理解CORS原理:浏览器的CORS策略是“先问后打”(Preflight),
mode只是前端开关。深入学习MDN CORS文档才能彻底掌握。
结语:别再让mode成为你的“隐形杀手”
mode属性不是可有可无的参数,而是跨域请求的“灵魂开关”。用对它,你的API请求畅通无阻;用错它,你将陷入CORS的无尽深渊。记住:
- 同源用
same-origin(仅限同源); - 只读资源用
no-cors(如图片、脚本); - 一切数据请求用
cors(必须服务器配合)。

5126

被折叠的 条评论
为什么被折叠?



