前后端分离使用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
关注公众号:
微信赞赏
支付宝赞赏
解决了一个小问题,感谢分享。