mp-mini-axios
Version:
MiniAxios 是一个轻量级 HTTP 客户端库,专为【微信小程序】设计,提供类似 Axios 的 API 接口。它支持请求/响应拦截器、取消请求、自动重试、文件上传/下载等功能。构建后大小11KB,能有效节省小程序包大小。
3 lines (2 loc) • 10.7 kB
JavaScript
/*! version: 1.6.3 */
class e{constructor(){this.aborted=!1,this.reason=null,this._eventListeners={}}addEventListener(e,t){this._eventListeners[e]||(this._eventListeners[e]=[]),this._eventListeners[e].push(t)}removeEventListener(e,t){if(!this._eventListeners[e])return;const r=this._eventListeners[e].indexOf(t);-1!==r&&this._eventListeners[e].splice(r,1)}dispatchEvent(e){this._eventListeners[e]&&this._eventListeners[e].forEach(t=>{try{t({type:e})}catch(e){}})}throwIfAborted(){if(this.aborted)throw this.reason}}class t extends Error{constructor(){super(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"请求被中止"),this.name="AbortError",this.code="ERR_ABORTED"}}class r{constructor(){this.signal=new e}abort(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"操作已中止";this.signal.aborted||(this.signal.aborted=!0,this.signal.reason=new t(e),this.signal.dispatchEvent("abort"))}}class s{constructor(e){this.message=e,this.name="Cancel"}toString(){return this.message?"".concat(this.name,": ").concat(this.message):this.name}}s.prototype.__CANCEL__=!0;class n{constructor(e){if("function"!=typeof e)throw new Error("executor must be a function");let t;this.promise=new Promise(e=>{t=e}),e(e=>{this.reason||(this.reason=new s(e),t(this.reason))})}throwIfRequested(){if(this.reason)throw this.reason}static source(){let e;return{token:new n(t=>{e=t}),cancel:e}}}function o(e,t,r){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var s=r.call(e,t);if("object"!=typeof s)return s;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);t&&(s=s.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),r.push.apply(r,s)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach(function(t){o(e,t,r[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))})}return e}class c{constructor(){this.handlers=[]}use(e,t){if("function"!=typeof e||t&&"function"!=typeof t)throw new Error("interceptor must be a function");return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1}eject(e){e>=0&&e<this.handlers.length&&(this.handlers[e]=null)}forEach(e){this.handlers.forEach(t=>{null!==t&&e(t)})}}class h{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.defaults=a({baseURL:"",timeout:6e4,headers:{},retry:!1,retryDelay:1e3},e),this.interceptors={request:new c,response:new c},this.request=this.request.bind(this),this.dispatchRequest=this.dispatchRequest.bind(this),this.handleResponseSuccess=this.handleResponseSuccess.bind(this),this.handleResponseError=this.handleResponseError.bind(this),this.setupRequestEvents=this.setupRequestEvents.bind(this),this.get=this.get.bind(this),this.post=this.post.bind(this),this.put=this.put.bind(this),this.delete=this.delete.bind(this),this.head=this.head.bind(this),this.options=this.options.bind(this),this.uploadFile=this.uploadFile.bind(this),this.downloadFile=this.downloadFile.bind(this),this.create=this.create.bind(this);const t=this.request.bind(this),r=Object.getOwnPropertyNames(h.prototype).filter(e=>"constructor"!==e);return Object.keys(this).concat(r).forEach(e=>{r.includes(e)?t[e]=this[e].bind(this):t[e]=this[e]}),t}request(e){if("object"!=typeof e||null===e)return Promise.reject(new Error("config must be an object"));if(!e.url)return Promise.reject(new Error("url is required"));if("uploadFile"===e.api&&!e.filePath)return Promise.reject(new Error("filePath is required"));try{const t=this.createInterceptorChain();(e=this.makeConfig(this.defaults,e)).debug&&console.log("init config",JSON.parse(JSON.stringify(e))),e.method&&(e.method=e.method.toLowerCase());let r=Promise.resolve(e);for(;t.length;)r=r.then(t.shift(),t.shift());return r}catch(e){return Promise.reject(e)}}makeConfig(e,t){return a(a(a({},e),t),this.mergeConfig(e,t))}mergeConfig(e,t){return{headers:a(a(a(a({},e.headers||{}),e.header||{}),t.headers||{}),t.header||{}),header:void 0,data:a(a(a(a({},e.data||{}),e.body||{}),t.data||{}),t.body||{}),body:void 0,params:a(a(a(a({},e.params||{}),e.query||{}),t.params||{}),t.query||{}),query:void 0}}buildFullUrl(e){if(!e.baseURL||/^https?:\/\//.test(e.url))return e.url;const t=e.baseURL.replace(/\/$/,""),r=e.url.replace(/^\//,"");return"".concat(t,"/").concat(r)}addQueryParams(e){if(!e.params||0===Object.keys(e.params).length)return e.url;const t=Object.entries(e.params).filter(e=>{let[t,r]=e;return null!=r}).map(e=>{let[t,r]=e;return Array.isArray(r)?r.map(e=>"".concat(encodeURIComponent(t),"=").concat(encodeURIComponent(e))).join("&"):"object"==typeof r?"".concat(encodeURIComponent(t),"=").concat(encodeURIComponent(JSON.stringify(r))):"".concat(encodeURIComponent(t),"=").concat(encodeURIComponent(r))}).join("&");if(!t)return e.url;const r=e.url.includes("?")?"&":"?";return"".concat(e.url).concat(r).concat(t)}createInterceptorChain(){const e=[];this.interceptors.request.forEach(t=>{e.push(t.fulfilled,t.rejected)});const t=[];this.interceptors.response.forEach(e=>{t.push(e.fulfilled,e.rejected)});const r=[this.dispatchRequest,void 0];return e.reverse().forEach(e=>{r.unshift(e)}),t.forEach(e=>{r.push(e)}),r}dispatchRequest(e){return new Promise((t,r)=>{try{let s;e.cancelToken&&"function"==typeof e.cancelToken.throwIfRequested&&e.cancelToken.throwIfRequested(),e.signal&&"function"==typeof e.signal.throwIfAborted&&e.signal.throwIfAborted();const n=e.cancelToken,o=e.signal;let i;const c=e.timeout||this.defaults.timeout||6e4;c>0&&(i=setTimeout(()=>{s&&s();const e=new Error("timeout of ".concat(c,"ms exceeded"));e.code="ETIMEDOUT",r(e)},c)),Object.assign(e,this.mergeConfig(this.defaults,e)),e.debug&&console.log("final config",e);let h,u,l=this.buildFullUrl(e);switch(l=this.addQueryParams(a(a({},e),{},{url:l})),e.api){case"downloadFile":h=wx.downloadFile,u={filePath:e.filePath};break;case"uploadFile":h=wx.uploadFile,u={filePath:e.filePath,name:e.name||e.fileName||"file",formData:e.formData||e.data||{}};break;default:h=wx.request,u={data:e.data}}const d=a(a({url:l},u),{},{header:e.headers,timeout:e.timeout,method:e.method||"get",dataType:e.dataType||"json",responseType:e.responseType||"text",enableCache:e.enableCache,enableHttp2:e.enableHttp2,enableQuic:e.enableQuic,success:s=>{clearTimeout(i),this.handleResponseSuccess(s,e,p,t,r)},fail:t=>{clearTimeout(i),this.handleResponseError(t,e,p,r)}});e.debug&&console.log("request config",d);const p=h(d);if(s=()=>{try{p.abort()}catch(e){console.warn("取消请求时出错:",e)}},n&&n.promise.then(e=>{s&&s(),r(e)}),o&&"function"==typeof o.addEventListener){const e=()=>{s&&s();const e=new Error("The request has been aborted");e.code="ECONNABORTED",r(e)};o.aborted?e():o.addEventListener("abort",e)}this.setupRequestEvents(p,e)}catch(e){r(e)}})}handleResponseSuccess(e,t,r,s,n){try{let o;if(o="downloadFile"===t.api?{tempFilePath:e.tempFilePath,filePath:e.filePath}:e.data,"string"==typeof o)try{o=JSON.parse(o)}catch(e){}const i={data:o,status:e.statusCode,statusText:"OK",headers:e.header,config:t,request:r};if(e.statusCode<200||e.statusCode>=300){const s=new Error("Request failed with status code ".concat(e.statusCode));s.code=e.statusCode>=500?"ERR_BAD_RESPONSE":"ERR_BAD_REQUEST",s.config=t,s.request=r,s.response=i,s.status=i.status,this.handleResponseError(s,t,r,n)}else s(i)}catch(e){n(e)}}handleResponseError(e,t,r,s){try{let n;if(h.isCancel(e)||"ECONNABORTED"===e.code||"ETIMEDOUT"===e.code||"ERR_BAD_RESPONSE"===e.code||"ERR_BAD_REQUEST"===e.code)n=e;else{const e=new Error((null==e?void 0:e.errMsg)||"request error");e.code="WX_API_ERROR",e.errno=void 0===(null==e?void 0:e.errno)?-1:e.errno,n=e}n.config=t,n.request=r,this.shouldRetry(n,t)?this.retryRequest(n,t,e=>e(),s):(t.__retryCount&&(n.retryCount=t.__retryCount),s(n))}catch(e){s(e)}}shouldRetry(e,t){if(h.isCancel(e)||"ECONNABORTED"===e.code||"ETIMEDOUT"===e.code)return!1;const r=t.retry;if(!r)return!1;return(t.__retryCount||0)<("number"==typeof r?r:1)}retryRequest(e,t,r,s){t.__retryCount=(t.__retryCount||0)+1;const n=this.calculateRetryDelay(t);"function"==typeof t.onRetry&&t.onRetry({retryCount:t.__retryCount,retryDelay:n,error:e}),setTimeout(()=>{this.dispatchRequest(t).then(r).catch(e=>{this.shouldRetry(e,t)?this.retryRequest(e,t,r,s):(t.__retryCount&&(e.retryCount=t.__retryCount),s(e))})},n)}calculateRetryDelay(e){const t=e.retryDelay||this.defaults.retryDelay||1e3,r=e.__retryCount||0;return t*Math.pow(2,r)}setupRequestEvents(e,t){try{const r={onHeadersReceived:t.onHeadersReceived,onChunkReceived:t.onChunkReceived,onProgressUpdate:t.onProgressUpdate};for(const[t,s]of Object.entries(r))"function"==typeof s&&"function"==typeof e[t]&&e[t](s)}catch(e){console.warn("设置请求事件监听器时出错:",e)}}get(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return this.request(a(a({},t),{},{url:e,method:"get"}))}post(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return this.request(a(a({},r),{},{url:e,data:t,method:"post"}))}put(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return this.request(a(a({},r),{},{url:e,data:t,method:"put"}))}delete(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return this.request(a(a({},t),{},{url:e,method:"delete"}))}head(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return this.request(a(a({},t),{},{url:e,method:"head"}))}options(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return this.request(a(a({},t),{},{url:e,method:"options"}))}uploadFile(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return e.url?(r=e,t=e.data,e=e.url):t.url&&(r=t,t=t.data),this.request(a(a({},r),{},{url:e,data:t,api:"uploadFile"}))}downloadFile(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.url&&(t=e,e=e.url),this.request(a(a({},t),{},{url:e,api:"downloadFile"}))}create(e){return new h(e)}static isCancel(e){return!(!e||!e.__CANCEL__)}}const u=new h;export{r as AbortController,n as CancelToken,h as MiniAxios,u as default};