问题描述

事情的起因是这样的,我试图在 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 格式的数据。这个问题通常出现在以下几个场景:

  1. 错误的 URL 或端点:确认你的请求 URL 或 API 端点是否正确。如果 URL 错误,服务器可能会返回 404 错误页面,而这些页面通常是 HTML 格式的。

  2. 服务器错误:如果服务器内部遇到错误,例如 500 内部服务器错误,它可能返回一个错误页面,而不是 JSON 数据。

  3. 未正确处理的请求:服务器可能没有适当地处理请求,尤其是当请求的资源不存在时,服务器可能返回一个 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 请求接口 啦!完美,大功告成~

警示

经此一事发现,搞技术还是要去 多多查看官方文档与官方库不要一有问题就去百度搜索,也不要过度“闭门造车”,要巧妙借助官方,它们将会成为你前进道路上的指路明灯,大大滴赞👍👍👍!