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的頁面?(可能是缺少位址或者代理配置錯誤)
如果一切看起來沒問題(新加的位址,服務端沒有重新開機),那就重新開機前端和後端伺服器,看看是不是問題解決了