@joker.front/requester
Version:
Joker 接口请求库,可通过该类库实现与@joker.server/core的快速对接。
2 lines (1 loc) • 4.34 kB
JavaScript
function e(e,t){let o=e.indexOf(t);return o>-1&&e.splice(o,1),e}function t(){let t=[];return{add:function(o){return t.push(o),()=>{e(t,o)}},callbacks:t,reset:function(){t=[]},remove:function(o){e(t,o)}}}const o="ERROR_CODE_REQUEST_BREAK",r="ERROR_CODE_REQUEST_ABORT",s="ERROR_CODE_REQUEST",a="ERROR_CDODE_TIME_OUT",i=/^(https?:\/\/|localhost)/;let n=new Map;class l{option;beforeCallbacks=t();afterCallbacks=t();errorCallbacks=t();constructor(e){this.option=e}requestList=[];async request(t,l){let c=Object.assign({url:t,method:"POST",timeout:10,rspType:"json"},l);if(!1===i.test(c.url)&&(c.url=(this.option.base||"")+c.url),!1===this.execBeforeEvent(c))return Promise.reject({code:o});if(c.data=await(this.option.transformReqData?.(c.data,c,this.option))??c.data,c.cache){!0===c.cache&&(c.cache={id:""});let e=`${c.url}|${c.cache?.id}`;if(c.forceRefreshCache)this.deleteCache(e);else{let t=this.getCache(e);if(void 0!==t){c.success?.(t);for(let e of this.afterCallbacks.callbacks)e(c,t);return Promise.resolve(t)}}}return new Promise(((t,o)=>{let i,f=new AbortController,h={option:c,cancel:()=>{f.abort()}},u=this.option.timeout;!1!==l?.timeout&&(u=l?.timeout),!1!==u&&u&&(i=setTimeout((()=>{f.abort();let e={code:a,message:"请求超时,请稍后重试",option:c};this.execError(e,o)}),1e3*u));let d=async(e,r)=>{let s=await(this.option.transformRspData?.(e,c,this.option))??e,a=e=>{c.cache&&(!0===c.cache&&(c.cache={id:""}),n.set(`${c.url}|${c.cache.id}`,{date:Date.now(),expiresIn:c.cache.expires,data:e}));try{c.success?.(e,r);for(let t of this.afterCallbacks.callbacks)t(c,e)}catch(e){console.error(e)}t(e)};this.option.analyRspResult?this.option.analyRspResult(s,(e=>{a(e)}),(e=>{this.execError(Object.assign(e,{option:c}),o,r)}),r):a(s)};if(this.option.mock)this.option.mock(c).then((async e=>{await d(e,{})})).finally((()=>{e(this.requestList,h),i&&clearTimeout(i)}));else{let{body:t,headers:a}=function(e){let t={};if(e&&"object"==typeof e)for(let o in e){let r=e[o];r&&(r instanceof File||r instanceof FileList||Array.isArray(r)&&r.length&&r[0]instanceof File)&&(t[o]=r)}for(let o in t)delete e[o];if(t&&!1===function(e){if(null==e)return!0;if(function(e){return null!==e&&"object"==typeof e}(e)){for(let t in e)return!1;return!0}return!1}(t)){let o=new FormData;for(let e in t){let r=t[e];if(r instanceof FileList||Array.isArray(r))for(let t of r)o.append(e,t);else o.append(e,r)}return o.append("jsonData",JSON.stringify(e)),{body:o,headers:{}}}return{body:JSON.stringify(e),headers:{"Content-Type":"application/json"}}}(c.data);fetch(c.url,{body:t,headers:Object.assign(a,c.headers),method:c.method,signal:f.signal}).then((async e=>{if(e.ok)if("stream"===c.rspType){let t=e.body?.getReader(),r=new TextDecoder;if(t)for(;;){let{done:o,value:s}=await t.read();if(r.decode(s).split("\n\n").filter(Boolean).map((e=>{const t=e.match(/^data:\s*(.*)/);t&&c.stream?.(t[1]||"")})),o){await d("",e);break}}else this.execError({code:e.status.toString(),message:"流式数据无响应",option:c},o)}else{let t=await e.json();await d(t,e)}else{let t=await e.text();this.execError({code:e.status.toString(),message:t??e.statusText,option:c},o)}})).catch((e=>{let t={code:"AbortError"===e.name?r:s,message:"AbortError"===e.name?void 0:e.message||"请求资源异常",option:c,e:e};"AbortError"!==e.name&&console.error(e),this.execError(t,o)})).finally((()=>{e(this.requestList,h),i&&clearTimeout(i)}))}this.requestList.push(h)}))}cancelAllRequest(e){for(let t of this.requestList)e&&!e(t.option)||t.cancel()}cancelRequest(e){for(let t of this.requestList)t.option.id===e&&t.cancel()}execBeforeEvent(e){for(let t of this.beforeCallbacks.callbacks)if(!1===t(e))return!1;return!0}deleteCache(e){n.delete(e)}getCache(e){let t=n.get(e);if(t)return t.date&&t.expiresIn&&Date.now()-t.date>t.expiresIn?void n.delete(e):t.data}execError(e,t,o){this.option.errorCodeMessage&&(e.message=this.option.errorCodeMessage[e.code]??e.message);try{for(let t of this.afterCallbacks.callbacks)t(e.option,e,o);for(let t of this.errorCallbacks.callbacks)t(e,o);if(e.option.error&&!1===e.option.error(e,o))return void t(e)}catch(e){console.error(e)}this.option.defaultErrorFunc&&this.option.defaultErrorFunc(e,o),t(e)}}export{a as ERROR_CDODE_TIME_OUT,r as ERROR_CODE_REQUEST_ABORT,o as ERROR_CODE_REQUEST_BREAK,s as ERROR_CODE_REQUEST_DEFAULT,l as Requester};