我看过axios文档,但它说的只是
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
Run Code Online (Sandbox Code Playgroud)
同样,许多教程仅显示此代码,但是我很困惑它的用途,有人可以给我简单的示例进行操作。
Ase*_*yay 31
简单来说,它是每个http操作的检查点。进行的每个api调用都会通过此拦截器传递。
那么,为什么要使用两个拦截器?
api调用由两个部分组成:一个请求和一个响应。由于它的行为类似于检查点,因此请求和响应具有单独的拦截器。
一些请求拦截器用例-
假设您要在发出请求之前进行检查,您的凭证有效吗?因此,您可以在拦截器级别检查您的凭据是否有效,而不是实际进行api调用。
假定您需要将令牌附加到每个请求,而不是在每个axios调用中复制令牌添加逻辑,您可以制作一个拦截器,在每个请求上附加一个令牌。
一些响应拦截器用例-
假设您有一个响应,并根据要确定用户已登录的api响应进行判断。因此,在响应拦截器中,您可以初始化一个处理用户登录状态的类,并在响应对象上相应地对其进行更新。收到。
假设您请求了一些具有有效api凭据的api,但是您没有有效的角色来访问数据。因此,您可以从响应拦截器发出警告,说不允许该用户。这样,您就可以避免必须对每个axios请求执行的未授权api错误处理。
现在可以提出这些用例。
希望这可以帮助 :)
编辑
由于此答案越来越受欢迎,因此这里有一些代码示例
请求拦截器
=>可以这样做(在这种情况下,通过检查环境变量)来打印axios的配置对象(如果需要):
const DEBUG = process.env.NODE_ENV === "development";
axios.interceptors.request.use((config) => {
/** In dev, intercepts request and logs it into console for dev */
if (DEBUG) { console.info("?? ", config); }
return config;
}, (error) => {
if (DEBUG) { console.error("?? ", error); }
return Promise.reject(error);
});
Run Code Online (Sandbox Code Playgroud)
=>如果要检查正在传递的标头/添加更多通用标头,则该标头在config.headers对象中可用。例如:
axios.interceptors.request.use((config) => {
config.headers.genericKey = "someGenericValue";
return config;
}, (error) => {
return Promise.reject(error);
});
Run Code Online (Sandbox Code Playgroud)
=>如果是GET请求,则可以在config.paramsobject中找到正在发送的查询参数。
响应拦截器
=>您甚至可以选择在拦截器级别解析api响应,并将解析后的响应向下传递而不是原始响应。如果在多个地方以相同的方式使用api,可能会节省您一次又一次编写解析逻辑的时间。一种方法是在中传递一个额外的参数,api-request然后在响应拦截器中使用相同的参数来执行操作。例如:
//Assume we pass an extra parameter "parse: true"
axios.get("/city-list", { parse: true });
Run Code Online (Sandbox Code Playgroud)
一次,在响应拦截器中,我们可以像这样使用它:
axios.interceptors.response.use((response) => {
if (response.config.parse) {
//perform the manipulation here and change the response object
}
return response;
}, (error) => {
return Promise.reject(error.message);
});
Run Code Online (Sandbox Code Playgroud)
因此,在这种情况下,只要中有一个parse对象response.config,便会完成操作,在其他情况下,它将按原样工作。
=>您甚至可以查看到达的HTTP代码,然后做出决定。例如:
axios.interceptors.response.use((response) => {
if(response.status === 401) {
alert("You are not authorized");
}
return response;
}, (error) => {
if (error.response && error.response.data) {
return Promise.reject(error.response.data);
}
return Promise.reject(error.message);
});
Run Code Online (Sandbox Code Playgroud)
Ste*_*e.g 18
例如,如果您想捕捉从发送请求到收到响应的时间,您可以使用此代码:
const axios = require("axios");
(async () => {
axios.interceptors.request.use(
function (req) {
req.time = { startTime: new Date() };
return req;
},
(err) => {
return Promise.reject(err);
}
);
axios.interceptors.response.use(
function (res) {
res.config.time.endTime = new Date();
res.duration =
res.config.time.endTime - res.config.time.startTime;
return res;
},
(err) => {
return Promise.reject(err);
}
);
axios
.get("http://localhost:3000")
.then((res) => {
console.log(res.duration)
})
.catch((err) => {
console.log(err);
});
})();
Run Code Online (Sandbox Code Playgroud)
Hum*_*mad 11
我将为您提供我在现实项目中使用的更多实际用例。我通常使用,request interceptor对于与令牌相关的人员(accessToken,refreshToken),例如,令牌是否未过期,如果是,则使用refreshToken更新它并保留所有其他调用直到它解决。但我最喜欢的是 axios,response interceptors您可以在其中放置应用程序的全局错误处理逻辑,如下所示:
httpClient.interceptors.response.use(
(response: AxiosResponse) => {
// Any status code that lie within the range of 2xx cause this function to trigger
return response.data;
},
(err: AxiosError) => {
// Any status codes that falls outside the range of 2xx cause this function to trigger
const status = err.response?.status || 500;
// we can handle global errors here
switch (status) {
// authentication (token related issues)
case 401: {
return Promise.reject(new APIError(err.message, 409));
}
// forbidden (permission related issues)
case 403: {
return Promise.reject(new APIError(err.message, 409));
}
// bad request
case 400: {
return Promise.reject(new APIError(err.message, 400));
}
// not found
case 404: {
return Promise.reject(new APIError(err.message, 404));
}
// conflict
case 409: {
return Promise.reject(new APIError(err.message, 409));
}
// unprocessable
case 422: {
return Promise.reject(new APIError(err.message, 422));
}
// generic api error (server related) unexpected
default: {
return Promise.reject(new APIError(err.message, 500));
}
}
}
);
Run Code Online (Sandbox Code Playgroud)
Con*_*ila 10
它就像一个中间件,基本上可以添加到任何请求(无论是GET,POST,PUT,DELETE)还是任何响应(从服务器获得的响应)上。它通常用于涉及授权的情况。
看看这个:Axios拦截器和异步登录
这是另一篇关于此的文章,并带有不同的示例:https : //medium.com/@danielalvidrez/handling-error-responses-with-grace-b6fd3c5886f0
因此,其中一个示例的要点是,您可以使用拦截器来检测您的授权令牌是否已过期(例如,如果您获得403)并重定向页面。
这个怎么样。您创建一个新的 Axios 实例并向其附加一个拦截器。然后您可以在应用程序中的任何位置使用该拦截器
export const axiosAuth = axios.create()
//we intercept every requests
axiosAuth.interceptors.request.use(async function(config){
//anything you want to attach to the requests such as token
return config;
}, error => {
return Promise.reject(error)
})
//we intercept every response
axiosAuth.interceptors.response.use(async function(config){
return config;
}, error => {
//check for authentication or anything like that
return Promise.reject(error)
})
Run Code Online (Sandbox Code Playgroud)
然后你用axiosAuth同样的方式使用axios
这是我在项目中经常采用的方法。该代码片段涉及如何在 axios 拦截器中使用访问和刷新令牌,并将有助于实现刷新令牌功能。
const API_URL =
process.env.NODE_ENV === 'development'
? 'http://localhost:8080/admin/api'
: '/admin-app/admin/api';
const Service = axios.create({
baseURL: API_URL,
headers: {
Accept: 'application/json',
},
});
Service.interceptors.request.use(
config => {
const accessToken = localStorage.getItem('accessToken');
if (accessToken) {
config.headers.common = { Authorization: `Bearer ${accessToken}` };
}
return config;
},
error => {
Promise.reject(error.response || error.message);
}
);
Service.interceptors.response.use(
response => {
return response;
},
error => {
let originalRequest = error.config;
let refreshToken = localStorage.getItem('refreshToken');
const username = EmailDecoder(); // decode email from jwt token subject
if (
refreshToken &&
error.response.status === 403 &&
!originalRequest._retry &&
username
) {
originalRequest._retry = true;
return axios
.post(`${API_URL}/authentication/refresh`, {
refreshToken: refreshToken,
username,
})
.then(res => {
if (res.status === 200) {
localStorage.setItem(
'accessToken',
res.data.accessToken
);
localStorage.setItem(
'refreshToken',
res.data.refreshToken
);
originalRequest.headers[
'Authorization'
] = `Bearer ${res.data.accessToken}`;
return axios(originalRequest);
}
})
.catch(() => {
localStorage.clear();
location.reload();
});
}
return Promise.reject(error.response || error.message);
}
);
export default Service;Run Code Online (Sandbox Code Playgroud)
我已经通过以下方式实现了
httpConfig.js
import axios from 'axios'
import { baseURL } from '../utils/config'
import { SetupInterceptors } from './SetupInterceptors'
const http = axios.create({
baseURL: baseURL
})
SetupInterceptors(http)
export default http
Run Code Online (Sandbox Code Playgroud)
安装拦截器.js
import { baseURL } from '../utils/config'
export const SetupInterceptors = http => {
http.interceptors.request.use(
config => {
config.headers['token'] = `${localStorage.getItem('token')}`
config.headers['content-type'] = 'application/json'
return config
},
error => {
return Promise.reject(error)
}
)
http.interceptors.response.use(function(response) {
return response
}, function (error) {
const status = error?.response?.status || 0
const resBaseURL = error?.response?.config?.baseURL
if (resBaseURL === baseURL && status === 401) {
if (localStorage.getItem('token')) {
localStorage.clear()
window.location.assign('/')
return Promise.reject(error)
} else {
return Promise.reject(error)
}
}
return Promise.reject(error)
})
}
export default SetupInterceptors
Run Code Online (Sandbox Code Playgroud)
参考:链接