使用fetch的no-cors模式时,如何区分网络错误与opaque响应?
核心问题
使用fetch的mode: 'no-cors'发起请求时,如何区分opaque响应与网络错误?
我认为:
- opaque响应会静默失败,fetch的Promise会resolve
- 网络错误会导致fetch的Promise reject
能否确认此结论?
背景
我想通过UI检测多个URL是否可达(例如未被防火墙拦截)。有资料提到:
no-cors模式意味着若浏览器需执行任何需要CORS权限的操作,会静默失败而非抛出错误。
具体问题
当使用带no-cors的fetch请求:
- 遇到网络错误时,是否会导致fetch的Promise reject?
- 遇到CORS问题时,是否会静默失败,即fetch的Promise resolve?
参考资料
- 支持:在Chrome开发者工具中模拟域名拦截的网络错误,结果符合上述结论,但不确定是否能真实反映实际网络错误。
- 反对:MDN文档未提及CORS异常会为fetch抛出TypeError
- 反对:fetch规范中提到:
换句话说,不透明过滤响应和不透明重定向过滤响应几乎无法与网络错误区分。
另外,能否通过CORS预检请求(或直接发送OPTIONS请求)检测不允许CORS的服务器是否可达?
回答
一、no-cors模式下的Promise状态判断
你的结论完全正确:
- Opaque响应(CORS限制导致):fetch的Promise会成功resolve,但返回的响应是"不透明"的——你无法读取响应状态码、响应头或响应体,仅能通过
response.type === 'opaque'识别。这就是文档中所说的"静默失败",不会抛出任何错误。 - 网络错误:包括DNS解析失败、连接超时、服务器拒绝连接、防火墙拦截等网络层面的问题,此时fetch的Promise会直接reject,并抛出
TypeError。
关于规范中提到的"几乎无法区分",是指你无法从响应内容判断opaque响应的具体原因(比如是服务器返回了200但被CORS过滤,还是返回了404但被过滤),但Promise的状态是明确区分网络错误和CORS限制的:reject对应网络不可达,resolve对应请求已发送(无论服务器是否允许CORS)。
二、关于OPTIONS请求检测可达性的可行性
不能通过CORS预检请求或直接发送OPTIONS请求实现更准确的可达性检测,逻辑和no-cors模式的普通请求一致:
- 若服务器不可达:OPTIONS请求会触发网络错误,Promise reject
- 若服务器可达但不允许CORS:浏览器会拦截响应并返回opaque响应,Promise resolve,但你无法读取任何响应细节
- 若服务器可达且允许CORS:你能正常读取响应状态码等信息,Promise resolve
本质上,用OPTIONS请求和用no-cors的GET/HEAD请求检测可达性的效果完全相同——只要Promise resolve,就说明网络层面能到达目标服务器;Promise reject则说明不可达。无需特意使用OPTIONS请求。
内容的提问来源于stack exchange,提问作者Rafael Emshoff
相关产品推荐
相关产品推荐

