Итак, у меня есть форма, которая отправляется со следующей функцией:
const formSubmit = async (formData) => {
const response = await SubmissionsResource.create(formData)
const { data, status } = response
console.info('Request completed.')
if (status === 201) {
toast.success('Submission created.')
} else {
toast.error('Something went wrong.')
console.error(data)
}
}
Который использует следующее:
const SubmissionsResource = {
create: ({ formData }) => (
Request.privatePost(apiUrl('submissions'), formData)
),
}
Который использует следующее:
export const Request = {
privateRequest: ({ data, method, params, url }) => {
axios.interceptors.request.use((request) => {
request.headers.authorization = getBearerToken()
return request
}, (error) => Promise.reject(error))
axios.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config
// If request is coming from a sign in attempt
if (error.response.status === 401 && originalRequest.url.includes('auth/token')) {
return Promise.reject(error)
}
// If request is coming from elsewhere, assume token might be expired
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true
const refresh_token = LocalStorageService.getRefreshToken()
const response = await axios.post(
`${API_BASE}/oauth/token`,
{ client_id, client_secret, grant_type: 'refresh_token', refresh_token }
)
if (response.status === 200) {
LocalStorageService.setUser(response.data)
axios.defaults.headers.common.Authorization = getBearerToken()
return axios(originalRequest)
}
return Promise.reject(error)
}
return Promise.reject(error)
}
)
return axios({ method, url, data, params })
},
privatePost: (url, data) => (
Request.privateRequest({ method: 'post', data, url })
)
}
Когда ответ успешен, я всегда вижу журнал «Запрос выполнен» и вижу сообщение toast.success
. Однако, когда запрос завершается неудачно, я никогда не вижу журнал «Запрос выполнен» или сообщение toast.error
.
Перехватчик axios должен повторить попытку один раз, если ответ возвращается неавторизованным (код состояния 401), что он успешно делает, а во всех остальных случаях отклоняет обещание и возвращает ошибку.
Request.privateRequest
должен отклонить обещание и вернуть ошибку Request.privatePost
, который должен вернуться обратно к SubmissionsResource.create
, а затем, наконец, к formSubmit
. Однако вместо того, чтобы выполнить промис и вернуть ошибку, он просто останавливает всю функцию и никогда не попадает в журнал «Запрос выполнен».
Я предполагаю, что это связано с неправильным пониманием обещаний с моей стороны, но я не могу понять, что это такое. Почему обещание не завершается и не переходит на следующую строку в formSubmit
?
Возвращая Promise.reject(), вы говорите axios отклонить обещание, возвращенное сетевым запросом, но вызывающий код не получает никакого отклонения.
Попробуйте попробовать:
const formSubmit = async (formData) => {
try {
const response = await SubmissionsResource.create(formData)
const { data, status } = response
console.info('Request completed.');
toast.success('Submission created.')
} catch(error) {
if (error.response.status === 401)
toast.error('Bad news: 401.');
else
toast.error('Some other kind of bad news.');
}
}
Да, это было проблемой. Спасибо!
Я не знаю ни одного из этих API, но, как правило, вы можете
throw new Error(x)
вместоreturn Promise.reject(x)
заставить цепочки промисов «распутываться». Попробуйте это и посмотрите, исправит ли это .... Еще одна вещь, которую вы можете попробовать: используйте отладчик по умолчанию, попробуйте установить точки останова и посмотрите, куда идет поток управления и что библиотека делает с результатом.