介绍
在大多数前端应用程序中,我们必须与后端集成在一起,随之而来的是我们可以使用的几个库,例如获取,ajax,axios等,每个库都有其特征,优势和缺点。
但是,无论我们在应用程序中要使用哪一个,我们都必须考虑要点以帮助我们进行维护和更好的沟通,以免影响用户的可用性。
在这篇文章中,我将使用Axios和React和应用概念,我认为我们在应用程序中应解决的问题非常重要。我将考虑到您已经安装了Axios的React项目。
1-封装服务
我们必须与库一起创建一个通用服务,我们选择将其用于集成,并只是在应用程序中使用它,并具有相同的组件诸如卡,输入等组件的想法。 p>
首先,我们必须创建一个http.js或http.ts file(请记住,如果需要,可以将另一个名称放置)才能用已经配置的后端的基本URL导出Axios。
import Axios from 'axios';
const http = Axios.create({
baseURL: process.env.REACT_APP_URL,
});
export default http;
现在,我们必须创建另一个index.js或index.ts文件,在其中我们将导出已经包含在尝试捕获博客中的最常用的HTTP方法,以处理此处的呼叫错误。在这里,我们已经在使用http.ts上方创建的文件来用参数触发axios,在以后的帖子中,我们将进化此文件。
import http from './http';
export default {
async get(url: string) {
try {
const response = await http.get(url);
return response;
} catch (err: any) {
return false;
}
},
async post(url: string, send: object) {
try {
const response = await http.post(url, send);
return response;
} catch (err: any) {
return false;
}
},
async put(url: string, send: object) {
try {
const response = await http.put(url, send);
return response;
} catch (err: any) {
return false;
}
},
async delete(url: string) {
try {
await http.delete(url);
return true;
} catch (err: any) {
return false;
}
},
};
最后,我们将拥有这样的文件夹结构。
我们将能够以这种方式调用组件上的方法。
await services.post( '/authenticate', { email, password } );
但是为什么有必要使用这种方法?
当我们使用通用服务并仅将其导入应用程序时,以后维护和修改变得更加简单。看看我们如何在下面做到这一点。
2-将标题添加到所有请求中
现在,让我们为我们的所有请求配置标头,我们需要此点才能传递令牌,以及您的后端可能需要作为业务规则所需的其他信息。
让我们为此创建一个Axios拦截器,因为它不仅是重复代码的最佳方法。请参阅下面的示例。
import Axios, { AxiosRequestConfig } from 'axios';
const http = Axios.create({
baseURL: process.env.REACT_APP_URL,
});
http.interceptors.request.use((config: AxiosRequestConfig) => {
const token = window.localStorage.getItem('token');
if (!token) return config;
if (config?.headers) {
config.headers = { Authorization: `Bearer ${token}` };
}
return config;
});
export default http;
在这里,我们已经检索了localstorage令牌并将其添加到后端的所有调用中。
3-重定向未经授权或未经验证的用户
当用户没有授权或许可时,我们必须具有用户重定向策略,以便他不需要在我们的组件中执行此操作。
为此,我们必须创建另一个拦截器来处理此过程。
import Axios, { AxiosRequestConfig } from 'axios';
const http = Axios.create({
baseURL: process.env.REACT_APP_URL,
});
http.interceptors.request.use((config: AxiosRequestConfig) => {
const token = window.localStorage.getItem('token');
if (!token) return config;
if (config?.headers) {
config.headers = { Authorization: `Bearer ${token}` };
}
return config;
});
http.interceptors.response.use(
(value) => {
return Promise.resolve(value);
},
(error) => {
const { isAxiosError = false, response = null } = error;
if (isAxiosError && response && response.status === 401) {
// User redirection rule for login page
return Promise.reject(error);
}
if (isAxiosError && response && response.status === 403) {
// User redirection rule for disallowed page
return Promise.reject(error);
}
return Promise.reject(error);
}
);
export default http;
请打开打开,您要向用户发送401和403(未经授权)的用户。这样,即使用户设法访问他无法访问的页面,当后端请求带有状态代码时,系统已经指导他,该方法也适用于代币到期时,我们将查看稍后如何处理。
4-请求重试模式
现在,我们需要对我们的请求应用模式重试,以便我们的最终用户不会在应用程序中遭受不稳定性的困扰,因为它可能在呼叫时正在进行基础架构的部署或自动缩放。为此,我们定义了许多尝试,以防系统返回错误500或更高的错误。下面的示例。
import Axios, { AxiosRequestConfig } from 'axios';
const http = Axios.create({
baseURL: process.env.REACT_APP_URL,
});
http.interceptors.request.use((config: AxiosRequestConfig) => {
const token = window.localStorage.getItem('token');
if (!token) return config;
if (config?.headers) {
config.headers = { Authorization: `Bearer ${token}` };
}
return config;
});
http.interceptors.response.use(
(value) => {
return Promise.resolve(value);
},
(error) => {
const { isAxiosError = false, response = null } = error;
if (isAxiosError && response && response.status === 401) {
// Regra de redirecionamento de usuário para página de login
return Promise.reject(error);
}
if (isAxiosError && response && response.status === 403) {
// Regra de redirecionamento de usuário para página de não permitido
return Promise.reject(error);
}
return Promise.reject(error);
}
);
let counter = 1;
http.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if (
error.response.status >= 500 &&
counter < Number(process.env.REACT_APP_RETRY)
) {
counter++;
return http.request(error.config);
}
counter = 1;
return Promise.reject(error);
}
);
export default http;
创建了一个拦截器,以便根据 process.env.react_app_retry 时间在请求大于500时的数字进行重试。
5-刷新令牌
当我们使用身份验证工作时,有一个很好的实践和安全规则,可以使该令牌到期,以便即使不使用该应用程序也不会永远登录。
但是,我们必须解决一个问题:如果令牌在用户不能简单地要求他再次登录时到期,因为我们有刷新令牌的路线。
我们可以改进我们的index.ts文件,以便在您的应用程序的路由电话中自动执行此操作。
import http from './http';
async function refreshToken() {
const value = Number(localStorage.getItem('expired'));
if (value && new Date(value) < new Date()) {
const result = await http.get('/refresh');
localStorage.setItem('token', result.data.token);
localStorage.setItem(
'expired',
String(new Date().setSeconds(result.data.expired))
);
}
}
export default {
async get(url: string) {
try {
await refreshToken();
const response = await http.get(url);
return response;
} catch (err: any) {
return false;
}
},
async post(url: string, send: object) {
try {
await refreshToken();
const response = await http.post(url, send);
return response;
} catch (err: any) {
return false;
}
},
async put(url: string, send: object) {
try {
await refreshToken();
const response = await http.put(url, send);
return response;
} catch (err: any) {
return false;
}
},
async delete(url: string) {
try {
await refreshToken();
await http.delete(url);
return true;
} catch (err: any) {
return false;
}
},
};
我们创建了一个RefReshToken()函数,该函数将在我们所有的应用程序调用之前始终被调用。它将检查令牌的过期是否已经过去,如果是的话,请对后端进行新的电话,续签令牌并过期。例如,请记住该逻辑根据后端和刷新路线起作用,例如,从过期到续订令牌后,它具有时间限制,这将更像是业务规则。
结论
在这篇文章中,我们看到了改善与后端的沟通并考虑到最终用户的最佳体验的五种方法,还有许多其他方法可以改善我们的后端呼叫服务,但是仅通过实施这些概念,我们就会具有更好的系统维护和可用性。在以后的帖子中,我们将看到如何进一步改善此服务。
参考
axios -https://axios-http.com/docs/intro
react -https://reactjs.org/