fetch returns SyntaxError: Unexpected token T in JSON at position 0

fetch returns SyntaxError: Unexpected token T in JSON at position 0

我正在尝试使用 Javascript 获取方法,但是,它似乎无法异步工作。

这是我的代码:

fetch(`${global.URL}${url}`, requestConfig)
  .then(res => res.json())
  .then(res => {
    console.log('response', res);
    return res;
  })
  .catch(error => {
    console.log('error: ', error)
  })

我有 70% 的时间收到以下错误,然后是 30%,收到有效响应,当我保存文件并重新呈现时,它有时会起作用。

error:  SyntaxError: Unexpected token T in JSON at position 0
    at parse (<anonymous>)
    at tryCallOne (core.js:37)
    at core.js:123
    at JSTimers.js:277
    at _callTimer (JSTimers.js:135)
    at _callImmediatesPass (JSTimers.js:183)
    at Object.callImmediates (JSTimers.js:446)
    at MessageQueue.__callImmediates (MessageQueue.js:396)
    at MessageQueue.js:144
    at MessageQueue.__guard (MessageQueue.js:373)

我试过在内部调用它和 async/await 函数,但没有用。

编辑 1:

这就是我提出请求的方式

const authenticityToken = global.TOKEN

const query = (url, config) => {
  const requestConfig = {
    credentials: 'same-origin',
    ...config,
    headers: {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json',
      Accept: 'application/json',
      Authorization: authenticityToken,
    },
  }

  return fetch(`${global.URL}${url}`, requestConfig)
  .then(res => res.json())
  .then(res => {
    console.log('response', res);
    return res;
  })
  .catch(error => {
    console.log('error: ', error)
  })
  // .then(handleResponseError)
}

export const get = (url, data) =>
  query(data ? `${url}?${stringify(data)}` : url)

export function fetchUser() {
  return (
    get('/api/v3/me/')
  )
}

然后我像这样在我的组件中调用函数:

  const fetchUserAction = () => {
    fetchUser()
    .then((response) => {
      if(response) setUser(response.data)
    })
  }

  useEffect(() => {
    fetchUserAction()
  }, [])

当您尝试解析的字符串无法解析为 JSON 时,总是会出现这种错误 Unexpected token T in JSON at position 0。此特定错误意味着字符串以字符 'T' 开头,而不是以“{”开头,因为可以解析为 JSON 的字符串应该以开头。有一种非常严格的格式可以让你的字符串成为一个对象。 如果您在后端确保您的代码接受一个对象、将其字符串化并发送文本,那么这可能不是问题。如果你知道在后端唯一可以发送的是一个字符串化的对象,那么那里可能没有错。

第二个更合理的答案是你的请求失败了,我看到你准备了一个 catch 块以防请求 returns 出错,但那里有问题。该请求可能由于多种原因而失败,如果您说它仅在某些时候发生,则可能是 CORS 问题或后端的逻辑错误。在这种情况下,您希望看到响应本身而不是已经解析的响应。本质上发生的是,当您的请求成功时,主体被成功解析为一个对象并且一切正常,但是当请求失败时,响应将是一个以 T 开头的异常,例如,当您尝试解析它失败,因为它以 T 而不是 JSON 开头。您需要看到的是解析为 JSON 之前的响应,只有当它不是错误时,您才应该尝试解析它。

您的代码中的问题在于,您做的第一件事就是尝试将其解析为 JSON。我建议您注释掉这一行并简单地将成功的请求或失败的请求打印为字符串。我很确定你会发现在 70% 的时间里,你会看到你期望的 JSON 字符串,而在剩下的 30% 中,你会得到一个异常字符串(它甚至可能由你的自动抛出)后端托管服务,如超时异常,它们可能不会被视为错误,而是被视为字符串。不幸的是,这种情况在 Firebase 函数的免费计划中经常发生,其中函数的时间 运行 被限制为一定数量秒,你应该在他们网站上的计划描述中检查它)以 T 开头。这肯定会通过为你提供更多信息来帮助你找到问题所在。

另一方面,我强烈建议您停止使用 then 和 catch,而是开始使用更高级的 async/await 语法,它可以帮助您保持代码的简单性和组织性。如果它与您所针对的所有引擎兼容,请阅读关于它的 Mozilla 文档,它非常简单:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

祝你有美好的一天,编码愉快

当您的服务器 return 不是 JSON 时,通常会发生此类错误。根据我的经验,99% 的时间服务器 return 正在发送一般错误消息。通常服务器会有一个通用的“捕获所有”错误处理程序,return类似于:

There was an error processing your request.

在这种情况下,如果您尝试使用 JSON.parse(或在您的情况下为 res.json()),您将收到遇到的错误。要查看此内容,请将其粘贴到您的控制台中:

JSON.parse("There was an error processing your request.")
//-> Uncaught SyntaxError: Unexpected token T in JSON at position 0

解决方法一:通常服务器在出错的时候都会设置一个合适的状态码。在解析之前检查以确保响应状态为 200:

fetch('...').then(res => {
  if (res.status !== 200) {
    throw new Error(`There was an error with status code ${res.status}`)
  }
  return res.json()
)

解决方案 2:将您的服务器代码更新为 return JSON 格式的错误消息。如果你使用的是 node 和 express,这看起来像这样:

function errorHandler (err, req, res, next) {
  if (res.headersSent) return next(err)

  const message = 'There was an error processing your request.'
  res.status(500)
  if (req.accepts('json')) {
    // The request contains the "Accept" header with the value "application/json"
    res.send({ error: message });
    return;
  }
  res.send(message);
}

然后,您将相应地更新您的前端代码:

fetch('...')
.then(res => res.json())
.then(res => {
  if (res.error) {
    throw new Error(res.error)
  }
  return res
)