Fetch API 报错 解决:SyntaxError: Unexpected token '<', "<!DOCTYPE"... is not valid JSON
问题描述
事情的起因是这样的,我试图在 Vue 项目中使用 Mock.js 模拟数据,在没有引入第三方库 axios 的情况下,直接使用 fetch 调用接口测试拦截请求。
mock('/api/users', 'get', { message: '测试数据'})
fetch('/api/users')
.then(res => res.json())
.then(data => console.log('fetchData', data))
.catch(err => console.error(err))
然后启动项目后控制台报错:SyntaxError: Unexpected token '<', "<!DOCTYPE"... is not valid JSON
思路历程
以下是 ChatGPT 给出的解答
遇到 "SyntaxError: Unexpected token '<', '<!DOCTYPE '... is not valid JSON" 这种错误通常是因为你的 JavaScript 代码期望从一个 fetch 请求中得到 JSON 格式的响应,但服务器实际返回的是 HTML 格式的数据。这个问题通常出现在以下几个场景:
错误的 URL 或端点:确认你的请求 URL 或 API 端点是否正确。如果 URL 错误,服务器可能会返回 404 错误页面,而这些页面通常是 HTML 格式的。
服务器错误:如果服务器内部遇到错误,例如 500 内部服务器错误,它可能返回一个错误页面,而不是 JSON 数据。
未正确处理的请求:服务器可能没有适当地处理请求,尤其是当请求的资源不存在时,服务器可能返回一个 HTML 页面,而非 JSON 格式的错误消息。
测试 axios 调接口是否正常
项目中安装 axios 后,测试 axios 调用接口是否正常,并通过 res.text() 打印出 fetch 接口返回的数据。
import axios from "axios"
mock('/api/users', 'get', { message: '测试数据'})
fetch('/api/users')
.then(res => res.text())
.then(data => console.log('fetchData', data))
.catch(err => console.error(err))
axios.get('/api/users').then(res => {
console.log('axiosData', res.data)
})
通过查看控制台的打印,我们发现 fetch 接口确实返回的 HTML 格式的数据!!!
但是引入第三方库 axios 来请求接口,发现没有任何报错信息,并且 Mock 可以正常拦截接口返回 Mock 中定义的数据。这就不得不怀疑可能是 fetch 的问题了!
json-server 搭 JSON 服务器
即便怀疑是 fetch 的问题,由于无从下手,还是先尝试利用 json-server 搭了个 JSON 服务器以模拟真实的服务器接口,得到一个本地可访问的接口:http://localhost:3000/users 。
再次测试真实可访问接口 http://localhost:3000/users <关于 json-server 的使用请参考我的另一篇文章:json-server>:
mock('http://localhost:3000/users', 'get', { id: 1, name: 'Jane', email: 'jane@example.com', age: 20 })
fetch('http://localhost:3000/users').then(res => res.json()).then(data => console.log(data))
axios.get('http://localhost:3000/users').then(res => {
console.log('axiosData', res.data)
})
通过结果来看,fetch 调用接口虽然可以正常拿到数据,但这个数据貌似是接口返回的,我的 Mock 拦截似乎并没有生效,axios 一切正常。
果然,没有对比就没有伤害,fetch 请求的拦截不生效,而 axios 一切正常。
……
几经曲折,最后通过查阅 Mock.js 的官方 Github 仓库,在 Issues 下发现了一样的问题。是的,没有猜错,Mock.js 官方库并未提供对 fetch 请求的拦截。啊哦,原来如此……
解决方案
解决方案: 既然 Mock 官方都不支持 fetch 请求的拦截了,那就只好 放弃 fetch,改用 axios 请求接口 啦!完美,大功告成~
警示
经此一事发现,搞技术还是要去 多多查看官方文档与官方库,不要一有问题就去百度搜索,也不要过度“闭门造车”,要巧妙借助官方,它们将会成为你前进道路上的指路明灯,大大滴赞👍👍👍!
- 感谢你赐予我前进的力量