Javascript 承诺解析函数返回未定义的
我为我想要使用的API编写了一个util包装器。包装器处理请求构建和令牌获取 从“./refreshToken”导入refreshTokenJavascript 承诺解析函数返回未定义的,javascript,reactjs,async-await,state,fetch-api,Javascript,Reactjs,Async Await,State,Fetch Api,我为我想要使用的API编写了一个util包装器。包装器处理请求构建和令牌获取 从“./refreshToken”导入refreshToken /** * Fetch util handles errors, tokens and request building for the wrapped API calls * @param {string} url Request URL e.g. /chargehistory * @param {string} requestMethod Req
/**
* Fetch util handles errors, tokens and request building for the wrapped API calls
* @param {string} url Request URL e.g. /chargehistory
* @param {string} requestMethod Request Method [GET, POST, PUT, DELETE]
* @param {object} requestBody Request Body as JSON object
* @param {object} retryFn The caller function as object reference to retry
* @private This function is only used as util in this class
* @async
*/
const fetchUtil = (url, requestMethod, requestBody, retryFn) => {
// Block thread if the token needs to be refetched
if(sessionStorage.getItem('token') == null || Number(sessionStorage.getItem('token_expiration')) < new Date().getTime()) {
refreshToken()
}
let request = {
method: requestMethod,
headers: {
'Authorization': `Bearer ${sessionStorage.getItem('token')}`,
'Content-Type': 'application/json'
}
}
if(requestMethod === 'POST' || requestMethod === 'PUT') {
request.body = JSON.stringify(requestBody)
}
fetch(`${process.env.REACT_APP_API}${url}`, request)
.then(response => {
if(response.ok) {
return response.json()
} else if(response.status === 401) {
refreshToken().then(() => retryFn())
} else {
console.error(`Error on fetching data from API: ${response.status}, ${response.text}`)
}
})
.then(json => {
console.log(json)
return json
})
.catch(error => console.error(error))
}
打印未定义的
,虽然我确实期望函数引用或承诺,但我多少能理解这一点。我尝试在fetchUtil和调用者之前添加
async
,并wait
fetchUtil。这给了我一个错误,没有调用undefined上的wait。我还试着把它重新编织成一个根本不起作用的钩子。我需要组件的
useffect
挂钩中的数据:
const Cockpit = () => {
const { t } = useTranslation()
const [chargehistory, setChargehistory] = useState(undefined)
const [installationreport, setInstallationreport] = useState(undefined)
useEffect(() => {
setChargehistory(getChargehistory)
setInstallationreport(getInstallationreport)
}, [])
}
为什么我得到了未定义的
以及如何解决这个问题?在fetchUtil
函数中,它以没有返回值结束,这意味着fetchUtil
函数将隐式返回未定义的
你说
fetch(`${process.env.REACT_APP_API}${url}`, request)
.then(response => {
if(response.ok) {
return response.json()
} else if(response.status === 401) {
refreshToken().then(() => retryFn())
} else {
console.error(`Error on fetching data from API: ${response.status}, ${response.text}`)
}
})
.then(json => {
console.log(json) // (1)
return json
})
.catch(error => console.error(error))
在这个函数中,(1)
部分工作正常,对吗
我想如果你像下面这样修改你的代码,它会工作的
首先,像这样更新fetchUtil
代码。回传
const fetchUtil = (url, requestMethod, requestBody, retryFn) => {
// Block thread if the token needs to be refetched
if(sessionStorage.getItem('token') == null || Number(sessionStorage.getItem('token_expiration')) < new Date().getTime()) {
refreshToken()
}
let request = {
method: requestMethod,
headers: {
'Authorization': `Bearer ${sessionStorage.getItem('token')}`,
'Content-Type': 'application/json'
}
}
if(requestMethod === 'POST' || requestMethod === 'PUT') {
request.body = JSON.stringify(requestBody)
}
// return fetch here! it will return a promise object.
return fetch(`${process.env.REACT_APP_API}${url}`, request)
.then(response => {
if(response.ok) {
return response.json()
} else if(response.status === 401) {
refreshToken().then(() => retryFn())
} else {
console.error(`Error on fetching data from API: ${response.status}, ${response.text}`)
}
})
.then(json => {
console.log(json)
return json
})
.catch(error => console.error(error))
}
因为我不能完全访问您的代码,所以可能仍然会有错误,但我希望这会有所帮助 在fetchUtil
函数中,在fetch
之前需要一个return关键字:return fetch(…)
。还请注意,您应该在fetchUtil
函数中处理错误,或者抛出错误以允许调用代码捕获并处理错误。个人我将从fetchUtil
函数中删除catch
方法调用,并在调用fetchUtil
函数的任何地方链接一个catch
方法。另一个解决方案是添加一个简单的回调函数作为参数并调用它,而不是返回承诺的最后一个函数确实解决了getChargehistory(installationId)中的问题,但它没有解决在useEffect()之后组件树中现在有一个挂起的结果的问题。您的意思是setChargehistory(getChargehistory)
part不起作用吗?如果是,这是因为getChargehistory
本身将promise对象返回为挂起状态。我认为如果你想用setChargehistory
设置结果,你必须在getChargehistory
函数中进行设置。这可能会有帮助!
const fetchUtil = (url, requestMethod, requestBody, retryFn) => {
// Block thread if the token needs to be refetched
if(sessionStorage.getItem('token') == null || Number(sessionStorage.getItem('token_expiration')) < new Date().getTime()) {
refreshToken()
}
let request = {
method: requestMethod,
headers: {
'Authorization': `Bearer ${sessionStorage.getItem('token')}`,
'Content-Type': 'application/json'
}
}
if(requestMethod === 'POST' || requestMethod === 'PUT') {
request.body = JSON.stringify(requestBody)
}
// return fetch here! it will return a promise object.
return fetch(`${process.env.REACT_APP_API}${url}`, request)
.then(response => {
if(response.ok) {
return response.json()
} else if(response.status === 401) {
refreshToken().then(() => retryFn())
} else {
console.error(`Error on fetching data from API: ${response.status}, ${response.text}`)
}
})
.then(json => {
console.log(json)
return json
})
.catch(error => console.error(error))
}
const getChargehistory = async (installationId) => {
const result = await fetchUtil(`/chargehistory?options.installationId=${installationId}`, 'GET', {}, getChargehistory)
console.log(result);
}