我正在尝试使用Javascript fetch方法,但是,它似乎不能异步工作。
这是我的代码:
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 的内容时,通常会发生这种类型的错误。根据我的经验,99% 的情况下服务器都会返回一般错误消息。通常,服务器会有一个通用的“捕获所有”错误处理程序,它返回类似以下内容:
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
解决方案1:通常每当出现错误时服务器都会设置一个适当的状态码。解析前检查确保响应状态为200:
fetch('...').then(res => {
if (res.status !== 200) {
throw new Error(`There was an error with status code ${res.status}`)
}
return res.json()
)
解决方案 2:更新服务器代码以返回 JSON 格式的错误消息。如果您使用的是节点和表达,这看起来像这样:
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
)
这种错误
Unexpected token T in JSON at position 0
总是在你尝试解析的字符串无法解析为 JSON 时发生。此特定错误意味着字符串以字符“T”开头,而不是以“{”开头,因为可以解析为 JSON 的字符串应该以开头。有一种非常严格的格式允许您的字符串成为一个对象。
如果您在后端确保代码接受一个对象,将其字符串化并发送文本,那么这可能不是问题。如果您知道后端唯一可以发送的东西是字符串化对象,那么那里可能没有任何问题。
第二个更合理的答案是您的请求失败,我看到您准备了一个 catch 块,以防请求返回错误,但那里有问题。请求可能因多种原因而失败,如果您说它只在某些时候发生,则可能是 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
祝你有美好的一天,快乐的编码
试试这个方法
const response = await fetch('https://apitest.authorize.net/xml/v1/request.api', {
method: 'post',
body: JSON.stringify(jsonBody),
headers: new Headers({'content-type': 'application/json',Accept: 'application/json',}),
});
const text = await response.text();
console.log(text);
return new Response(text, { status: 200, statusText: 'OK', headers: { 'Content-Type': 'application/json' } });