mode: 'no-cors' 仅允许发送简单跨域请求但无法读取响应,适用于单向上报等无需响应的场景;需读响应时应配置服务端CORS或使用代理。

使用 mode: 'no-cors' 并不能真正“处理”跨域请求,它只是让 Fetch 请求绕过浏览器的跨域限制检查,但同时也会大幅限制你能获取的响应内容——你只能得到一个不透明(opaque)响应,无法读取状态码、响应头或响应体。
为什么 mode: 'no-cors' 看似能发请求,实则功能受限
当你设置 mode: 'no-cors' 时,浏览器会允许你发出一个“简单请求”(即满足 CORS 预检豁免条件:方法为 GET/HEAD/POST,且只含安全请求头如 Accept、Content-Type(仅限 application/x-www-form-urlencoded、multipart/form-data、text/plain)),但它不会暴露响应数据。此时:
- 响应的
type是'opaque',不是'basic'或'cors' -
response.status恒为 0,response.statusText为空字符串 -
response.headers是空的(不可读) -
response.json()、response.text()等方法会抛出 TypeError
什么场景下才该用 no-cors?
它只适用于一种目的:**向第三方服务发送“单向”请求,且你完全不需要响应内容**。典型例子包括:
- 向分析服务(如某些埋点接口)上报日志或事件
- 触发 Webhook(如通知后端执行某个操作,无需等待返回)
- 向广告或监控像素 URL 发起 GET 请求(类似
<img src="...">)
注意:这些场景本质是“发了就完”,不是“请求-响应”交互。
如果你需要读取响应,正确做法是什么?
必须由服务端配合开启 CORS,而不是前端强行用 no-cors。关键点:
- 服务端需在响应头中返回
Access-Control-Allow-Origin: *(或指定域名) - 若涉及 Cookie 或认证头(如
Authorization),还需设置Access-Control-Allow-Credentials: true,且前端 Fetch 要加credentials: 'include' - 非简单请求(如带自定义 header、
Content-Type: application/json)会触发预检(OPTIONS),服务端必须正确响应预检请求
替代方案:代理或服务端中转
当无法控制目标服务端(比如调用第三方 API 且对方不支持 CORS),可借助自己的后端做代理:
- 前端请求你的服务器(同源),例如
/api/proxy?url=https://third-party.com/data - 你的服务器发起真实 HTTP 请求,拿到响应后原样返回给前端(此时无跨域问题)
- 可在此过程中添加鉴权、缓存、错误统一处理等逻辑
这是最可控、最通用的解法,也是生产环境推荐的方式。
不复杂但容易忽略:no-cors 不是跨域“解决方案”,而是跨域“规避手段”,只适用于单向通信。真要读响应,CORS 配置或代理才是正路。










