如何使用适配器更改 Axios 中的结果状态?

问题描述 投票:0回答:3

原因

我们正在使用 axios-retry 库,它在内部使用此代码:

axios.interceptors.response.use(null, error => {

由于它只指定了错误回调,所以Axios文档说:

任何超出 2xx 范围的状态码都会导致此功能触发

不幸的是,我们正在调用一个非 RESTful API,它可能会返回 200,并在正文中包含错误代码,我们需要重试。

我们尝试在 axios-retry 之前添加一个 Axios 拦截器,并在这种情况下更改结果状态;但这并没有触发后续的拦截器错误回调。

所做的工作是指定自定义适配器。然而,这并没有很好的记录,我们的代码并不能处理所有情况。 代码

const axios = require('axios'); const httpAdapter = require('axios/lib/adapters/http'); const settle = require('axios/lib/core/settle'); const axiosRetry = require('axios-retry'); const myAdapter = async function(config) { return new Promise((resolve, reject) => { // Delegate to default http adapter return httpAdapter(config).then(result => { // We would have more logic here in the production code if (result.status === 200) result.status = 500; settle(resolve, reject, result); return result; }); }); } const axios2 = axios.create({ adapter: myAdapter }); function isErr(error) { console.log('retry checking response', error.response.status); return !error.response || (error.response.status === 500); } axiosRetry(axios2, { retries: 3, retryCondition: isErr }); // httpstat.us can return various status codes for testing axios2.get('http://httpstat.us/200') .then(result => { console.log('Result:', result.data); }) .catch(e => console.error('Service returned', e.message));

这适用于错误情况,打印:

重试检查响应 500 重试检查响应 500 重试检查响应 500 重试检查响应 500 服务返回 请求失败,状态码 500

它也适用于成功案例(将 URL 更改为 
http://httpstat.us/201

): 结果:{代码:201,描述:'已创建'}

问题

将 URL 更改为

http://httpstat.us/404

会导致: (节点:19759)UnhandledPromiseRejectionWarning:错误:请求失败,状态代码为 404 在createError处(.../node_modules/axios/lib/core/createError.js:16:15) 解决时(.../node_modules/axios/lib/core/settle.js:18:12)

catch
调用上的

httpAdapter

 将捕获该错误,但我们如何将其传递到链中?
实现 Axios 适配器的正确方法是什么?

如果有更好的方法来处理这个问题(除了分叉 axios-retry 库),那将是一个可以接受的答案。

更新

一位同事发现,在

.catch(e => reject(e))

通话中执行

.catch(reject)

(或只是 
httpAdapter
)似乎可以解决该问题。然而,我们仍然希望有一个实现包装默认 http 适配器的 Axios 适配器的规范示例。

这是有效的(在节点中):
node.js axios adapter axios-retry
3个回答
6
投票
const httpAdapter = require('axios/lib/adapters/http'); const settle = require('axios/lib/core/settle'); const customAdapter = config => new Promise((resolve, reject) => { httpAdapter(config).then(response => { if (response.status === 200) // && response.data contains particular error { // log if desired response.status = 503; } settle(resolve, reject, response); }).catch(reject); }); // Then do axios.create() and pass { adapter: customAdapter } // Now set up axios-retry and its retryCondition will be checked

拦截器和自定义错误的解决方法

1
投票
const axios = require("axios").default; const axiosRetry = require("axios-retry").default; axios.interceptors.response.use(async (response) => { if (response.status == 200) { const err = new Error("I want to retry"); err.config = response.config; // axios-retry using this throw err; } return response; }); axiosRetry(axios, { retries: 1, retryCondition: (error) => { console.log("retryCondition"); return false; }, }); axios .get("https://example.com/") .catch((err) => console.log(err.message)); // gonna be here anyway as we'll fail due to interceptor logic

如果您的应用程序运行在浏览器环境中,您应该使用axios内置的XHR适配器。

0
投票
import xhrAdapter from 'axios/lib/adapters/xhr'; import settle from 'axios/lib/core/settle'; function customAdapter(config: AxiosRequestConfig): any { return new Promise((resolve, reject) => { xhrAdapter(config) .then((response: AxiosResponse) => { if (xxx) { response.status = 401; } settle(resolve, reject, response); }) .catch(reject); }); }


© www.soinside.com 2019 - 2024. All rights reserved.