React调用Markdown API出现Uncaught (in promise)错误求助
问题概述
调用Markdown指南的API时出现Uncaught (in promise) SyntaxError: Unexpected end of input错误。使用React编写的代码中添加了mode: 'no-cors'配置,打印响应对象得到:
Response {type: 'opaque', url: '', redirected: false, status: 0, ok: false, …}body: (...)bodyUsed: falseheaders: Headers {}ok: falseredirected: falsestatus: 0statusText: ""type: "opaque"url: ""[[Prototype]]: Response
请求状态码为0,无法正常解析JSON内容。
错误原因
no-cors模式的限制:当使用mode: 'no-cors'发起请求时,浏览器会创建opaque类型的响应,这种响应的body、status等核心属性无法被前端JavaScript读取,调用resp.json()时自然没有可解析的内容,从而抛出Unexpected end of input错误。- 跨域问题本质:添加
no-cors通常是为了绕过浏览器的CORS(跨域资源共享)限制,但这只是“隐藏”了错误,并没有真正解决跨域问题——目标API可能没有配置允许你的前端域名访问,导致直接请求被浏览器拦截。
解决方法
方法1:移除no-cors模式(优先尝试)
先尝试直接移除mode: 'no-cors'配置,检查目标API是否支持CORS:
import React, { useState } from 'react' const Docs = () => { const [docs, setDocs] = useState([]); const fetchDocs = async () => { try { const resp = await fetch("https://www.markdownguide.org/api/v1/basic-syntax.json"); // 检查请求是否成功 if (!resp.ok) { throw new Error(`请求失败,状态码:${resp.status}`); } const data = await resp.json(); console.log(data); setDocs(data); } catch (error) { console.error('获取文档失败:', error); } } return ( <div> <button onClick={fetchDocs}>Docs</button> </div> ) } export default Docs
如果API本身配置了允许跨域,这个修改就能直接解决问题;如果依然出现CORS错误,再尝试下面的代理方案。
方法2:使用后端代理(解决CORS限制)
如果目标API不支持CORS,最可靠的方式是通过后端服务转发请求,避免浏览器的跨域拦截。
方案A:React项目内置代理(create-react-app适用)
在项目的package.json中添加代理配置:
"proxy": "https://www.markdownguide.org"
然后修改前端的请求路径:
const resp = await fetch("/api/v1/basic-syntax.json");
启动项目后,React会自动将以/api开头的请求转发到配置的代理地址,从而绕过跨域限制。
方案B:自定义Node.js代理服务
如果不是create-react-app项目,可以自己搭建一个简单的Node.js代理:
const express = require('express'); const axios = require('axios'); const app = express(); const port = 3001; app.get('/api/v1/basic-syntax.json', async (req, res) => { try { const response = await axios.get('https://www.markdownguide.org/api/v1/basic-syntax.json'); res.json(response.data); } catch (error) { res.status(500).send('代理请求失败'); } }); app.listen(port, () => { console.log(`代理服务运行在 http://localhost:${port}`); });
启动代理服务后,前端请求改为:
const resp = await fetch("http://localhost:3001/api/v1/basic-syntax.json");
方法3:JSONP(仅API支持时可用)
如果目标API支持JSONP格式,可以通过JSONP方式请求,但该API返回的是纯JSON,大概率不支持此方式,因此仅作为补充方案提及。
内容的提问来源于stack exchange,提问作者we learn

