前言
自入职以来,感觉生活着实是变得很忙碌,虽然是实习生,但工作依然是被安排的很充足。每天等着9点领完夜宵再下班已经是常态了,回到出租屋洗完澡已是10点,此后虽然还想着再学些什么却又更想还是看一会儿视频就睡觉好了。五一假期亦没有出行,一是没有想一起出游的伙伴,二是确实想好好休息下,与其出去受罪我还是想在学校歇着,玩一玩好久没动的游戏,看看书什么的。
说回此篇文章,在我实习经历中,我自己一直都在做的是类似于打杂的工作,主要时间都是在基于师兄建好的框架上进行页面的开发,虽然说在项目中这样的工作是占了绝大部分,但毫无疑问,那些前期基础的工作对于项目来说才是举足轻重的,是否掌握这些工程化的知识,也是区分前端工程师和前端切图仔的重要标准。出于掌握并分享知识的目的,我决定分为几个系列步骤,逐步搭建一个自己的React项目脚手架。
封装axios
将axios根据业务的需求封装为对外暴露的request方法,整体代码还是比较简单明了的,这里就不再过多解释,代码中也有注释,其中还用到了一个decodehtml方法,是用来将后端返回的富文本错误信息进行展示。
/** decodeHtml */
export const decodeHtml = (html: string): string => {
let oDiv = document.createElement('div');
oDiv.innerHTML = html;
const textContent = oDiv.textContent;
oDiv = null;
return textContent;
};
以下为request方法的代码(src/utils/request.ts)
import { Message, Dialog } from '@alifd/next';
import axios, { AxiosRequestConfig } from 'axios';
import { decodeHtml } from '@/utils';
export interface IRequest extends AxiosRequestConfig {
url: string;
/** 请求参数,当method为post的时候请使用data属性 */
params?: any;
/** 当method为post的时候使用data属性 */
data?: any;
/**
* 是否缓存数据,相同url数据只请求一次,后面的请求都使用第一次请求的数据
*/
cache?: boolean;
/** 更据 cacheKey 进行缓存, 当cache 为true时生效 */
cacheKey?: string;
/**
* 错误时是否Message提示错误信息, 默认开启
*/
enableErrorMsg?: boolean;
// 缓存有效期
maxAge?: number;
[key: string]: any;
}
// 缓存存储对象,当项目大了的时候考虑释放内存,目前不需要
const request_cache = {};
export interface IResult {
success?: boolean;
code?: string;
message?: string;
data?: any;
[key: string]: any;
}
// 设置为ajax请求
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/**
* 数据请求
* @example
* request({
* url: '/a/b/c',
* params: {}
* })
* // res.success === true的时候执行 then
* .then(res => {...})
* // res.success === false 的时候执行 catch
* .catch(res => {...})
*
* 请配合 `ahooks` 的 `useRequest` 使用 https://ahooks.js.org/hooks/async#dependent-request
*/
export default ({
cache = false,
enableErrorMsg = true,
cacheKey = '',
maxAge = Infinity, //过期时间
...params
}: IRequest) => {
// 本地缓存,只请求一次
if (cache && request_cache[`${params.url}-${cacheKey}`]) {
if (request_cache[`${params.url}-${cacheKey}`].then) {
return request_cache[`${params.url}-${cacheKey}`];
} else if (
new Date().getTime() -
request_cache[`${params.url}-${cacheKey}`].cacheTime <
maxAge
) {
return new Promise(resolve => {
resolve(request_cache[`${params.url}-${cacheKey}`].res);
});
}
} else if (request_cache[`${params.url}-${cacheKey}`]) {
delete request_cache[`${params.url}-${cacheKey}`];
}
if (params.method && params.method.toLowerCase() === 'post') {
// post时传入参数是data字段
params.data = params.data || params.params || undefined;
// params.data = qs.stringify(params.data); // 和后端约定 post请求用json的方式传递数据,所以关掉
params.params = undefined;
params.headers = params.headers || {
'Content-Type': 'application/json;charset=UTF-8', // 和后端约定 post请求用json的方式传递数据
};
// 如果需要做csrf可以采用以下方案,需要后端先在接口返回信息中设置cookie
// if (!isLocal()) {
// const csrfToken = getCookie('XSRF-TOKEN');
// if (csrfToken) {
// params.headers['X-XSRF-TOKEN'] = csrfToken;
// } else {
// Message.error('cookie获取失败'); // XSRF-TOKEN cookie 缺失
// throw new Error('cookie获取失败');
// }
// }
} else if (
!params.method ||
(params.method && params.method.toLowerCase() === 'get')
) {
// get时传入的参数是params字段
params.params = params.params || params.data || undefined;
}
const servicePromise = new Promise((resolve, reject) => {
axios(params)
.then(({ data: res, status }: IResult) => {
const { message, success, data, code } = res;
if (success && status === 200) {
// 成功
// 需要缓存的数据缓存下来
cache &&
(request_cache[`${params.url}-${cacheKey}`] = {
res,
cacheTime: new Date().getTime(),
});
resolve(res);
} else if (code === '9003') {
// 状态过期重定向,后端code为9003,这里的code每个团队有自己的规范
Dialog.confirm({
content: `状态已过期,是否重新刷新页面? `,
onOk: () => {
window.location.reload();
},
});
} else if (data?.applyUrl) {
// 临时处理无权限跳转
window.location.href = data.applyUrl;
reject(res);
} else {
// 失败
// 失败时是否展示错误信息
enableErrorMsg &&
Message.error(
`[${params.apiName || params.url}]: ${decodeHtml(message)}`
);
reject(res);
}
})
.catch(e => {
// 接口非200 || 接口非304
enableErrorMsg && Message.error(`[http]: ${e}`);
reject(e);
});
});
//缓存这里需要考虑一种情况是,在第二次请求发出时,第一次请求还未完成
//那么可以先把第一次请求操作缓存,第二次请求时判断若还在pending中,则返回promise对象,否则返回结果
if (cache) {
request_cache[`${params.url}-${cacheKey}`] = servicePromise;
}
return servicePromise;
};
使用方式
应用中所有的请求方法都放在 src/services/ 目录下,每个模块/页面使用的请求方法放在一个对应的js/ts文件中。
//src/services/examplePage.ts
import request from '@/utils/request';
export const exampleApi = ({ data, ...elseConfig }) => {
return request({
url: `/api/reputation/evaluation/deepInsight/emotion`,
method: 'post',
data,
...elseConfig,
});
};
在页面中使用,推荐搭配ahooks
的 useRequest使用
import {exampleApi} from '@/services/examplePage.ts';
import { useRequest } from 'ahooks';
const { data, error, loading } = useRequest(()=>exampleApi({
data:{
yourInfo:''
},
cache:true,
maxAge:360000
});
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!