@coon/utils
Version:
251 lines (230 loc) • 6.26 kB
text/typescript
import axios from 'axios';
import utils from './utils'
type CacheItem = { [prop: number]: any }
enum Method {
GET = 'get',
POST = 'post',
HEAD = 'head',
REQUEST = 'request',
DELETE = 'delete',
PUT = 'put',
PATCH = 'patch',
OPTIONS = 'options',
}
interface IOption {
apis: any
config: any
// vuex: boolean
adapter: string
}
interface IUseOption {
// 请求参数
params?: any
// 请求发送的数据
data?: any
// restful风格化数据
rest?: any
// 强制更新
forceUpdate?: boolean
// 请求超时时间
timeout?: number
// 此次请求的过期时间
expire?: number | string
}
interface IApi {
// url地址
url?: string
// 请求类型
type?: Method
// 缓存过期时间
expire?: number | string
// 请求超时时间
timeout?: number
// 默认数据
default?: any
}
interface IFullParams extends IUseOption, IApi {
}
// 默认配置
const defaultConfig = {
type: Method.GET,
adapter: 'axios'
}
export default class NoneData {
// 缓存数据都以过期时间为key的方式存在于此
/**
* key为0时表示session
* {
* 0:['keyName0'],
* 1616383496048:['keyName1','keyName2'],
* }
*
*/
public cache: CacheItem
public option: IOption
public state: any
public config: any
public apis: {
[prop: string]: any
}
public adapter: string
static adapters = {
axios: axios,
}
constructor(option: IOption) {
this.option = option;
this.state = {};
this.config = option.config;
this.adapter = option.adapter;
this.apis = {};
this.cache = {}
}
public getAdapter() {
return NoneData.adapters[this.adapter];
}
public async use(apiKey: string, option: IUseOption = {}) {
const fullParams: IFullParams = this.getFullParams(apiKey, option);
this.apis[apiKey] = { ...fullParams, apiKey };
// 如果没有配置url则直接返回默认数据或已存在的数据
if (!fullParams.url) {
return this.getData(apiKey, fullParams);
}
// 将扩展url解析为正常url及请求方式
// 如果强制更新或者已经过期或者state中没有数据则发送请求
if (fullParams.forceUpdate || this.hadExpire(apiKey) || !this.state[apiKey]) {
return this.request(fullParams);
}
}
// 判断是否已经过期
public hadExpire(apiKey: string) {
}
// 获取单次请求的完整参数
public getFullParams(apiKey: string, option: IUseOption): IFullParams {
const api = this.getApiFromKey(apiKey);
const params = this.parseEurl(api, option);
return utils.merge({}, params, option) as IFullParams;
}
// 通过apikey获取api对象
/**
// api对象格式如下:
{
// url地址
url:'user/info',
// 请求类型
type:'get',
// 缓存过期时间
expire:0,
// 请求超时时间
timeout:0,
// 默认数据
default:{},
}
// option对象的格式如下
{
// 请求参数
params:{},
// 请求发送的数据
data:{},
// restful风格化数据
rest:{},
// 强制更新
forceUpdate:true,
// 请求超时时间
timeout:0,
// 此次请求的过期时间
expire:0,
}
*/
public getApiFromKey(apiKey: string) {
//把apiKey分隔成两部分moduleName & apiName
const [moduleName, ...tApiName] = apiKey.split('.');
const apiName = tApiName.join('.');
let api = this.option.apis?.[moduleName]?.[apiName];
if (!api) {
console.warn(`noneData数据:${apiKey}未配置`);
return false;
}
// 扩展的url
if (typeof api === 'string') {
// if (api[0] == ' ' || !/^(request|get|post|delete|head|options|put|patch)\s/.test(api)) {
// api = (' ' + api).replace(/^\s+/, ' ')
// }
api = { url: api }
}
return api;
}
public requestHandler(res) {
debugger;
}
// 解析形如 'post api/userOther/:userId/:pageSize/:pageNo 100s' 的URL
public parseEurl(api: any, option: any) {
let eurl = api.url || '';
if (eurl?.[0] == ' ' || !/^(request|get|post|delete|head|options|put|patch)\s/.test(eurl)) {
eurl = (' ' + eurl).replace(/^\s+/, ' ')
}
const [dtype, furl, sexpire = '0'] = eurl.split(' ');
const expire = utils.parseTime(sexpire);
const type = api.type || (option.data ? 'post' : dtype) || Method.GET;
let url = furl;
if (option.rest) {
url = this.restUrl(furl, option.rest);
}
return { url, type, expire }
}
// 解析restURL
public restUrl(furl = '', restObj = {}) {
// const restKeys=furl.match(/\{\w+\}/g);
const restKeys = furl.match(/\:[^\/\b]+/g);
restKeys?.forEach(item => {
furl = furl.replace(item, restObj[item.replace(':', '')] || '')
});
return furl;
}
// 获取数据
public getData(apiKey: string, fullParams: IFullParams) {
// 如果未配置url取本地数据
return this.state[apiKey] || fullParams.default;
}
// 发送请求
public async request(fullParams: IFullParams) {
// if ()
}
}
// 使用方法-----------------------------------------------------------------------
// 在此之前需要如下的api配置
const apis = {
moduleName: {
// remote api data
'user.info': ' api/userInfo', // 'get api/userInfo'
// rest api
'userOther': 'api/userOther/{userId}/{pageSize}/{pageNo}',
// 默认本地数据,如果有url,就去请求
'userStore': { expire: 'session', url: 'api/userStore', type: 'post', timeout: 0, },
// 本地默认空数据
'userBlank': { default: {} },
// 直接在此也可配置缓存时间(单位为秒),作为此请求的默认缓存时间使用
'userLogs': { expire: 10 },
}
}
// 配置
const nd = new NoneData({
apis,
config: {},
// 使用vuex
// vuex: true,
// adapter用来发送请求的,比如axios,uni.callFunction,uni.request等等。
adapter: 'axios'
})
// store 版 vuex
// 使用可能带本地缓存的服务器数据
// const data=await nd.use('moduleName.user.info', {
// // 强制远程更新
// forceUpdate:false,
// // 单独配置缓存时间 单位毫秒
// cache: 1000,
// type: 'post',
// rest:,
// params:,
// // 有此参数时默认切换为post请求,除非配置了type
// data:,
// })