前后端分离使用localStorage替代cookies并封装到umi-request组成跨终端请求插件wldos-request
做过前后端分离的都知道,cookies不是万能的,为了兼容移动端可以采用localStorage,然后做一些封装实现类cookies功能。前端token等凭据的保存依赖于HTTP请求和响应,umi3.0的umi-request插件是个好用的插件,两者结合就成了本文所述的跨终端请求插件。
本插件包含两部分:localStorage封装和request封装。

localstorage封装代码如下:
const expirefix = "__expires__";
/**
* @desc 在localStorage基础上封装支持过期时间的storage,代替cookie。
* @author zhiletu.com
* @version 1.0
*/
class wldostorage {
constructor() {
this.source = localStorage;
this.init();
}
init(){
/**
* @desc 初始化localstorage
* @param {String} key 键
* @param {String} value 值,若存储数组、对象,需要通过JSON.stringify转换为json字符串
* @param {String} expired 过期时间,以分钟为单位
*/
const reg = new RegExp(expirefix);
const data = this.source;
const list = Object.keys(data);
if(list.length > 0){
list.map((item)=>{
const { key } = item;
if( !reg.test(key)){
const now = Date.now();
const expires = data[`${key}${expirefix}`]||Date.now+1;
if (now >= expires ) {
this.remove(key);
};
};
return key;
});
};
}
remove(key) {
const data = this.source;
const value = data[key];
delete data[key];
delete data[`${key}${expirefix}`];
return value;
}
get(key) {
/**
* @desc 从localstorage获取项
* @param {String} key 键
* @param {String} expired 存储时为非必须字段,所以有可能取不到,默认为 Date.now+1
*/
const { source } = this;
const expired = source[`${key}${expirefix}`]||Date.now+1;
const now = Date.now();
console.log('wldostorage get>>>', source, expired, now);
if ( now >= expired ) {
this.remove(key);
return undefined;
}
return source[key] ? JSON.parse(source[key]) : source[key];
}
set(key, value, expired) {
/**
* @desc 设置localStorage项
* @param {String} key 键
* @param {String} value 值
* @param {Number} expired 过期时间,以分钟为单位,非必填
*/
const { source } = this;
source[key] = JSON.stringify(value);
if (expired){
source[`${key}${expirefix}`] = Date.now() + 1000*60*expired
};
return value;
}
}
// eslint-disable-next-line new-cap const wldosStorage = new wldostorage();
[/erphpdown]
export default wldosStorage;
与umi-request结合封装代码如下:
/** * umi-request 网络请求工具 * 更详细的 api 文档: umi-rqeust */ import { extend } from 'umi-request'; import { notification } from 'antd'; import {refreshTokenService} from "@/services/login"; import {setAuthority} from "@/utils/authority"; import wldosStorage from "@/utils/wldostorage"; const codeMessage = { 200: '服务器成功返回请求的数据。', 201: '新建或修改数据成功。', 202: '一个请求已经进入后台排队(异步任务)。', 204: '删除数据成功。', 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。', 401: '用户没有权限(令牌、用户名、密码错误)。', 403: '用户得到授权,但是访问是被禁止的。', 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。', 406: '请求的格式不可得。', 410: '请求的资源被永久删除,且不会再得到的。', 422: '当创建一个对象时,发生一个验证错误。', 500: '服务器发生错误,请检查服务器。', 502: '网关错误。', 503: '服务不可用,服务器暂时过载或维护。', 504: '网关超时。', }; /** * 异常处理程序 */ const errorHandler = (error) => { const { response } = error; if (response && response.status) { const errorText = codeMessage[response.status] || response.statusText; const { status, url } = response; notification.error({ message: `请求错误 ${status}: ${url}`, description: errorText, }); } else if (!response) { notification.error({ description: '您的网络发生异常,无法连接服务器', message: '网络异常', }); } return response; }; /** * 配置request请求时的默认参数 */ const req = extend({ errorHandler, // 默认错误处理 credentials: 'include', // 默认请求是否带上cookie }); const request = (url, params) => {
const { method = 'GET' } = params || {};
const options = {
method,
headers: { // umi-request默认Content-Type为application/json,此处省略。
'X-CU-AccessToken-WLDOS': wldosStorage.get('accessToken'),
},
};
if (method === 'GET') {
Object.assign(options,
// method为get,umi-request默认为get
params, // get方法数据域schema为params,表示请求参数,完整写法是:params: {key: value,...}
);
} else {
Object.assign(options, {
// method可以为:POST、PATCH、PUT、DELETE
data: params.data, // post方法数据域schema为data,表示要提交的数据,完整写法是:data: {key: value,...}
});
}
console.log('request>> url, params, options>>>>', url, params, options);
return req(url, options)
/* .then((res) => {
return checkStatus(res, url, options);
}) .catch(err => ({
err
})) */;
};
// 文件上传
const postFile = (url, params) => {
const formData = new FormData();
formData.append('file', params);
return request(url, { method:'post', data: formData });
};
export { postFile };
export default request;
// 使用方法示例:
// POST请求:
export async function queryCurrentBook(params) {
return request('/api/currentBook', {
method: 'POST',
data: params,
});
}
// GET请求:
export async function queryCurrentChapter(params) {
return request('/api/currentChapter', {
params,
});
}
// mock接收参数示例:
'POST /api/currentBook': async (req, res) => {
const { userid, bookId } = req.body;
console.log('当前年谱id:', userid, req.body);
}
'GET /api/currentChapter': async (req, res) => {
const {userid, chapterId, bookId } = req.query;
console.log('请求章节userid, bookId, chapterId, req.body:', userid, bookId, chapterId, req.query);
}
声明: 除非转自他站(如有侵权,请联系处理)外,本文采用 BY-NC-SA 协议进行授权 | 嗅谱网
转载请注明:转自《前后端分离使用localStorage替代cookies并封装到umi-request组成跨终端请求插件wldos-request》
本文地址:http://www.xiupu.net/archives-10929.html
关注公众号:
微信赞赏
支付宝赞赏

解决了一个小问题,感谢分享。