Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0 当你发送一个 HTTP 请求,可能是用 Fetch 或者其他的 Ajax 库,可能会出现这个错误提示,或者相似的错误。接下来我将解释这是由什么引起的,我们应该怎样解决这些问题
1. 引起的原因
这些错误发生在当你向服务器发送请求,返回值不是 JSON 而用 JSON 的方法解析的时候,发生这种情况的代码可能是这样的。
fetch(‘/users’).then(res => res.json())
实际的请求没有问题,它得到了一个返回值,发生问题的关键在于 res.json()。
2. JSON.parse
用另一种方法 JSON.parse 来解析 Json 的,代码可能是这样的
JSON.parse(` 不是 Json 的字符串 `);
JSON.parse() 本质上是和 res.json() 一样的,所以它们发生错误的情况是相同的。
3. 无效的 JSON
JSON 应该以有效的 JSON 值开始 —— 一个 object, array, string, number, 或者是 false/true/null。以 < 开始的返回值会有 Unexpected token < 这样的提示。< 这个符号意味着返回值是 HTML 而不是 JSON。引起这个错误的根源是服务端返回的是 HTML 或者其他不是 Json 的字符串。
为什么会这样呢?“Unexpected token o in JSON at position 1”或者其他变量。错误的提示一些差别会随着服务器返回的不同而不同
它所提示的符号或者位置可能不同,但是引起它的原因是相同的:你的代码所有解析的 Json 不是真的有效的 Json。下面是一些我所看见的错误的提示:
Unexpected token < in JSON at position 1
Unexpected token p in JSON at position 0
Unexpected token d in JSON at position 0
4. 解决方案
With fetch, you can use res.text() instead of res.json() to get the text string itself. Alter your code to read something like this, and check the console to see what’s causing the problem: 首先要做是先把返回值打印出来。如果用 fetch,可以用 res.text() 代替 res.json() 来获得字符串。把你的代码转换成如下这样,并且通过打印出来的内容查看哪里出问题了。
fetch(‘/users’)
// .then(res => res.json()) // comment this out for now
.then(res => res.text()) // convert to plain text
.then(text => console.log(text)) // then log it out
注意像 res.json() 和 res.text() 这样的方法是异步的。所以不能直接把它们的返回值打印出来,这就是 console.log 必须在.then 的括号里面的原因。
5. 是因为服务器的原因吗?
服务器有好几种原因返回 HTML 而不是 JSON:
请求的 url 不存在,服务器以 HTML 的方式返回 404 页面。你可能在请求时代码写错(像把 /user 写成了 /users), 或者服务端的代码的错误。
当添加了新的路由时,服务器需要重启。比如你在用 Express 写的服务器时,刚刚新加了一个 app.get(‘/users’, …) 路由,但是没有重启,服务器就不会对新的路由地址有反应。
客户端的代理没有设置:如果在使用像 Create React App 的 Webpack dev server 时,你可以设置一个指向后端服务器的代理。
API 的根 url 是 /, 如果你在通过 Webpack 或 Create React App 使用代理, 要确认你的 API 路由不在根的层级 /。这样会时代理服务器混淆,你将得到一个 HTML 而不是你的 API 请求的返回。你可以在如有前面加个前缀像 /api/。
同时可以通过 devtools 的 network 查看请求的返回值。
是不是 404 页面?(可能是缺少该地址或者代码输入错误)。这是不是 index.html 的页面?(可能是缺少地址或者代理配置错误)
如果一切看起来没问题(新加的地址,服务端没有重启),那就重启前端和后端服务器,看看是不是问题解决了