diff --git a/docs/zh/reference/plugin/plugins/request.md b/docs/zh/reference/plugin/plugins/request.md index 0978d242..03fd2594 100644 --- a/docs/zh/reference/plugin/plugins/request.md +++ b/docs/zh/reference/plugin/plugins/request.md @@ -117,6 +117,27 @@ request('/api/login', { }) ``` +### merge 重复请求 + +连续发送多个请求,会被合并成一个请求,不会报 `REPEAT` 接口错误。 + +当发生 `REPEAT` 请求异常,并且确保自身代码合理的情况下,可以使用该配置。 + +```js +import {request} from '@fesjs/fes'; + +request('/api/login', { + username: 'robby', + password: '123456' +}, { + mergeRequest: true, // 在一个请求没有回来前,重复发送的请求会合并成一个请求 +}).then((res) => { + // do something +}).catch((err) => { + // 处理异常 +}) +``` + ### 请求节流 ```js @@ -145,7 +166,7 @@ request('/api/login', { }, { cache: { cacheType: 'ram', // ram: 内存,session: sessionStorage,local:localStorage - cacheTime: 1000 * 60 * 3 // 缓存时间,默认3min + cacheTime: 1000 * 60 * 3 // 缓存时间:默认3min }, }).then((res) => { // do something @@ -156,6 +177,7 @@ request('/api/login', { 若 `cache` 传 `true`,则默认使用 `ram` 缓存类型,缓存时间 3min。 + ### 结合 use 使用 ```js diff --git a/packages/fes-plugin-request/src/template/cacheControl.js b/packages/fes-plugin-request/src/template/cacheControl.js index 28ca451d..4de45132 100644 --- a/packages/fes-plugin-request/src/template/cacheControl.js +++ b/packages/fes-plugin-request/src/template/cacheControl.js @@ -39,7 +39,6 @@ import { const CACHE_KEY_PREFIX = '__FES_REQUEST_CACHE:'; const CACHE_TYPE = { - merge: 'merge', // merge 重复请求 ram: 'ram', session: 'sessionStorage', local: 'localStorage' @@ -64,9 +63,6 @@ function setCacheData({ data, cacheTime = 1000 * 60 * 3 }) { - // merge 类型没有缓存 - if (cacheType === CACHE_TYPE.merge) return; - const _key = genInnerKey(key, cacheType); const currentCacheData = { @@ -100,9 +96,6 @@ function isExpire({ expire, cacheTime }) { } function getCacheData({ key, cacheType = 'ram' }) { - // merge 类型没有缓存 - if (cacheType === CACHE_TYPE.merge) return; - const _key = genInnerKey(key, cacheType); if (cacheType !== CACHE_TYPE.ram) { const cacheInstance = window[CACHE_TYPE[cacheType]]; @@ -170,20 +163,9 @@ function handleCachingQueueError(ctx, config) { const _key = genInnerKey(ctx.key, config.cache.cacheType); const queue = cachingQueue.get(_key); if (queue && queue.length > 0) { - // 非 merge 类型,进行队列重试,直到有一个请求成功,后面的全部成功 - if (config.cache.cacheType !== CACHE_TYPE.merge) { - const firstResolve = queue.shift(); - firstResolve(); - cachingQueue.set(_key, queue); - } else { - queue.forEach((resolve) => { - resolve({ - error: ctx.error - }); - }); - cachingQueue.delete(_key); - cacheStartFlag.delete(_key); - } + const firstResolve = queue.shift(); + firstResolve(); + cachingQueue.set(_key, queue); } else { cachingQueue.delete(_key); cacheStartFlag.delete(_key); diff --git a/packages/fes-plugin-request/src/template/preventRepeatReq.js b/packages/fes-plugin-request/src/template/preventRepeatReq.js index 379a109b..4c5ee34f 100644 --- a/packages/fes-plugin-request/src/template/preventRepeatReq.js +++ b/packages/fes-plugin-request/src/template/preventRepeatReq.js @@ -1,17 +1,63 @@ const requestMap = new Map(); -export default async (ctx, next) => { - const key = ctx.key; - if (requestMap.get(key)) { - ctx.error = { - type: 'REPEAT', - msg: '重复请求' - }; - return; +const mergeRequestMap = new Map(); +const requestQueue = new Map(); + +function handleCachingStart(ctx) { + const isRequesting = mergeRequestMap.get(ctx.key); + if (isRequesting) { + return new Promise((resolve) => { + const queue = requestQueue.get(ctx.key) || []; + requestQueue.set(ctx.key, queue.concat(resolve)); + }); + } + mergeRequestMap.set(ctx.key, true); +} + +function handleRepeatRequest(ctx) { + const queue = requestQueue.get(ctx.key); + if (queue && queue.length > 0) { + queue.forEach((resolve) => { + if (ctx.error) { + resolve({ + error: ctx.error + }); + } else { + resolve({ + response: ctx.response + }); + } + }); + } + requestQueue.delete(ctx.key); + mergeRequestMap.delete(ctx.key); +} + +export default async (ctx, next) => { + if (ctx.config.mergeRequest) { + const result = await handleCachingStart(ctx); + if (result) { + Object.keys(result).forEach((key) => { + ctx[key] = result[key]; + }); + return; + } + } else { + if (requestMap.get(ctx.key) && !ctx.config.mergeRequest) { + ctx.error = { + type: 'REPEAT', + msg: '重复请求' + }; + return; + } + requestMap.set(ctx.key, true); } - requestMap.set(key, true); await next(); - requestMap.delete(key); + if (ctx.config.mergeRequest) { + handleRepeatRequest(ctx); + } else { + requestMap.delete(ctx.key); + } }; diff --git a/packages/fes-template-h5/src/pages/index.vue b/packages/fes-template-h5/src/pages/index.vue index 33634157..0b72617b 100644 --- a/packages/fes-template-h5/src/pages/index.vue +++ b/packages/fes-template-h5/src/pages/index.vue @@ -22,9 +22,21 @@ export default { const clickIcon = () => { console.log('click Icon'); }; - request('/api', null).then((res) => { - console.log(res); - }); + // request('/api', null, { + // mergeRequest: true + // }).then((res) => { + // console.log(res); + // }); + // request('/api', null, { + // mergeRequest: true + // }).then((res) => { + // console.log(res); + // }); + // request('/api', null, { + // mergeRequest: true + // }).then((res) => { + // console.log(res); + // }); // request('/api', null, { // throttle: 3000, // cache: true @@ -56,27 +68,21 @@ export default { // }); // }, 3200); - // request('/api', null, { - // cache: { - // cacheType: 'merge' - // } - // }).then((res) => { - // console.log(res); - // }); - // request('/api', null, { - // cache: { - // cacheType: 'merge' - // } - // }).then((res) => { - // console.log(res); - // }); - // request('/api', null, { - // cache: { - // cacheType: 'merge' - // } - // }).then((res) => { - // console.log(res); - // }); + request('/api', null, { + cache: true + }).then((res) => { + console.log(res); + }); + request('/api', null, { + cache: true + }).then((res) => { + console.log(res); + }); + request('/api', null, { + cache: true + }).then((res) => { + console.log(res); + }); // request('/api', null, { // // skipErrorHandler: [500]