UNPKG

uni-lala

Version:

一个uniapp请求工具,promisify,类axios,带拦截器

189 lines (160 loc) 4.69 kB
const COMMON_REQUEST_METHODS = ['get', 'post', 'put', 'delete', 'connect', 'head', 'options', 'trace'] const FILE_REQUEST_METHODS = ['uploadFile', 'downloadFile'] function createInterceptors() { let _resolve = null let _reject = null const ret = { p: null } function _reset() { ret.p = _resolve = _reject = null } function lock() { ret.p = new Promise((resolve, reject) => { _resolve = resolve _reject = reject }) } function unlock() { if (_resolve) { _resolve() _reset() } } function cancel() { if (_reject) { _reject('canceled') _reset() } } ret.interceptors = { lock, unlock, cancel, request: { use(handler) { this.handler = handler } }, response: { use(handler, errHandler) { this.handler = handler this.errHandler = errHandler } } } return ret } function enqueueIfLocked(p, cb) { if (p) { p.then(async () => await cb?.()) } else { cb?.() } } function isPlainObject(obj) { return Object.prototype.toString.call(obj).slice(8, -1) === 'Object' } function mergeOptions(target, source, root = true) { const res = { ...target } for (const k in source) { const baseURL = source['baseURL'] if (root && k === 'baseURL' && baseURL) { const reqUrl = res['url'] if (typeof reqUrl === 'undefined' || /^https?:\/\//.test(reqUrl)) { continue } // 去掉前面的斜线`/` const i = reqUrl.search(/\w/) const path = i === -1 ? '' : reqUrl.slice(i) if (baseURL.endsWith('/')) { res['url'] = baseURL + path } else { res['url'] = [baseURL, path].filter(Boolean).join('/') } continue } if (res.hasOwnProperty(k)) { if (isPlainObject(res[k]) && isPlainObject(source[k])) { res[k] = mergeOptions(res[k], source[k], false) } } else { res[k] = source[k] } } return res } function innerRequest(requestType, options) { return new Promise((resolve, reject) => { requestType({ ...options, async success(res) { resolve((await options.success?.(res)) ?? res) }, async fail(err) { reject((await options.fail?.(err)) ?? err) }, async complete(res) { await options.complete?.(res) } }) }) } function createInstance(defaultOptions) { const interceptorsContainer = createInterceptors() const { interceptors } = interceptorsContainer function _request(options) { return new Promise((resolve, reject) => { enqueueIfLocked(interceptorsContainer.p, async () => { const originConfig = mergeOptions(options, defaultOptions) const config = (await Promise.resolve(interceptors.request.handler?.(originConfig))) ?? originConfig function resolveCallback(response) { enqueueIfLocked(interceptorsContainer.p, async () => { const res = (await Promise.resolve(interceptors.response.handler?.(response, config, options))) resolve(res ?? response) }) } async function rejectCallback(error) { enqueueIfLocked(interceptorsContainer.p, async () => { const err = (await Promise.resolve(interceptors.response.errHandler?.(error, config, options))) reject(err ?? error) }) } const { method, ...optionsExceptMethod } = config if (!method || COMMON_REQUEST_METHODS.includes(method.toLowerCase())) { innerRequest(uni.request, config).then(resolveCallback, rejectCallback) } else if (method === 'uploadFile') { innerRequest(uni.uploadFile, optionsExceptMethod).then(resolveCallback, rejectCallback) } else if (method === 'downloadFile') { innerRequest(uni.downloadFile, optionsExceptMethod).then(resolveCallback, rejectCallback) } else { reject(new Error('method is not supported or WRONG invoke style.')) } }) }) } _request.interceptors = interceptors _request.lock = interceptors.lock _request.unlock = interceptors.unlock _request.cancel = interceptors.cancel COMMON_REQUEST_METHODS.forEach(method => { _request[method] = (url, data, options) => _request({ url, data, ...options, method: method.toUpperCase() }) }) FILE_REQUEST_METHODS.forEach(method => { _request[method] = (url, options) => _request({ url, ...options, method }) }) return _request } export default createInstance({}) export function create(defaultOptions = {}) { return createInstance(defaultOptions) }