You've already forked guangan-mp
1.0.0
This commit is contained in:
103
uni_modules/uni-ajax/js_sdk/index.d.ts
vendored
Normal file
103
uni_modules/uni-ajax/js_sdk/index.d.ts
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
export type AnyObject = { [x: string]: any }
|
||||
|
||||
export type Data = string | AnyObject | ArrayBuffer
|
||||
export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'HEAD' | 'OPTIONS' | 'TRACE'
|
||||
export type DataType = 'json' | 'text' | 'html'
|
||||
export type ResponseType = 'text' | 'arraybuffer'
|
||||
|
||||
export interface RequestTask {
|
||||
abort: () => void
|
||||
onHeadersReceived?: (listener: (header: any) => void) => void
|
||||
offHeadersReceived?: (listener: (header: any) => void) => void
|
||||
}
|
||||
|
||||
export interface FetcherInstance<T = any> {
|
||||
resolve: (value: T) => void
|
||||
reject: (reason?: any) => void
|
||||
source: () => Promise<T>
|
||||
abort: () => Promise<void>
|
||||
}
|
||||
|
||||
export interface FetcherConstructor {
|
||||
new <T = RequestTask>(): FetcherInstance<T>
|
||||
}
|
||||
|
||||
export interface CustomConfig {}
|
||||
|
||||
export interface AjaxRequestConfig extends CustomConfig {
|
||||
baseURL?: string
|
||||
url?: string
|
||||
data?: Data
|
||||
query?: AnyObject
|
||||
params?: AnyObject
|
||||
header?: any
|
||||
method?: Method
|
||||
timeout?: number
|
||||
dataType?: DataType
|
||||
responseType?: ResponseType
|
||||
sslVerify?: boolean
|
||||
withCredentials?: boolean
|
||||
firstIpv4?: boolean
|
||||
fetcher?: FetcherInstance
|
||||
validateStatus?: ((statusCode?: number) => boolean) | null
|
||||
adapter?: (config: AjaxRequestConfig) => Promise<any>
|
||||
}
|
||||
|
||||
export type AjaxConfigType =
|
||||
| AjaxRequestConfig
|
||||
| (() => AjaxRequestConfig)
|
||||
| (() => Promise<AjaxRequestConfig>)
|
||||
| void
|
||||
|
||||
export interface AjaxResponse<T = any> {
|
||||
data: T
|
||||
statusCode: number
|
||||
header: any
|
||||
config: AjaxRequestConfig
|
||||
errMsg: string
|
||||
cookies: string[]
|
||||
}
|
||||
|
||||
export interface AjaxInterceptorManager<V> {
|
||||
use<T = V>(onFulfilled?: (value: V) => T | Promise<T>, onRejected?: (error: any) => any): number
|
||||
eject(id: number): void
|
||||
}
|
||||
|
||||
export interface CustomResponse<T = any> {}
|
||||
|
||||
export type AjaxResult<T> = keyof CustomResponse extends never ? AjaxResponse<T> : CustomResponse<T>
|
||||
|
||||
export interface AjaxInvoke {
|
||||
<T = any, R = AjaxResult<T>>(config?: AjaxRequestConfig): Promise<R>
|
||||
<T = any, R = AjaxResult<T>>(url?: string, data?: Data, config?: AjaxRequestConfig): Promise<R>
|
||||
}
|
||||
|
||||
export interface AjaxInstance<T extends AjaxConfigType> extends AjaxInvoke {
|
||||
get: AjaxInvoke
|
||||
post: AjaxInvoke
|
||||
put: AjaxInvoke
|
||||
delete: AjaxInvoke
|
||||
connect: AjaxInvoke
|
||||
head: AjaxInvoke
|
||||
options: AjaxInvoke
|
||||
trace: AjaxInvoke
|
||||
getURL(config?: AjaxConfigType): Promise<string>
|
||||
readonly defaults: AjaxRequestConfig
|
||||
readonly config: T
|
||||
interceptors: {
|
||||
request: AjaxInterceptorManager<AjaxRequestConfig>
|
||||
response: AjaxInterceptorManager<AjaxResponse>
|
||||
}
|
||||
}
|
||||
|
||||
export interface AjaxStatic extends AjaxInstance<void> {
|
||||
create<T extends AjaxConfigType = void>(config?: T): AjaxInstance<T>
|
||||
Fetcher: FetcherConstructor
|
||||
}
|
||||
|
||||
declare const Ajax: AjaxStatic
|
||||
declare const Fetcher: FetcherConstructor
|
||||
|
||||
export { Fetcher }
|
||||
|
||||
export default Ajax
|
14
uni_modules/uni-ajax/js_sdk/index.js
Normal file
14
uni_modules/uni-ajax/js_sdk/index.js
Normal file
@ -0,0 +1,14 @@
|
||||
import Ajax from './lib/core/Ajax'
|
||||
import Fetcher from './lib/adapters/Fetcher'
|
||||
|
||||
const ajax = Ajax()
|
||||
|
||||
ajax.create = function create(instanceConfig) {
|
||||
return Ajax(instanceConfig)
|
||||
}
|
||||
|
||||
ajax.Fetcher = Fetcher
|
||||
|
||||
export { Fetcher }
|
||||
|
||||
export default ajax
|
22
uni_modules/uni-ajax/js_sdk/lib/adapters/Fetcher.js
Normal file
22
uni_modules/uni-ajax/js_sdk/lib/adapters/Fetcher.js
Normal file
@ -0,0 +1,22 @@
|
||||
const PROMISE = Symbol('$$promise')
|
||||
|
||||
export default class Fetcher {
|
||||
get [Symbol.toStringTag]() {
|
||||
return '[object Fetcher]'
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this[PROMISE] = new Promise((resolve, reject) => {
|
||||
this.resolve = resolve
|
||||
this.reject = reject
|
||||
})
|
||||
}
|
||||
|
||||
async source() {
|
||||
return this[PROMISE]
|
||||
}
|
||||
|
||||
async abort() {
|
||||
;(await this.source())?.abort()
|
||||
}
|
||||
}
|
16
uni_modules/uni-ajax/js_sdk/lib/adapters/http.js
Normal file
16
uni_modules/uni-ajax/js_sdk/lib/adapters/http.js
Normal file
@ -0,0 +1,16 @@
|
||||
export default function adapter(config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const requestTask = uni.request({
|
||||
...config,
|
||||
complete: result => {
|
||||
// 根据状态码判断要执行的触发的状态
|
||||
const response = { config, ...result }
|
||||
!config.validateStatus || config.validateStatus(result.statusCode)
|
||||
? resolve(response)
|
||||
: reject(response)
|
||||
}
|
||||
})
|
||||
|
||||
config.fetcher?.resolve(requestTask)
|
||||
})
|
||||
}
|
72
uni_modules/uni-ajax/js_sdk/lib/core/Ajax.js
Normal file
72
uni_modules/uni-ajax/js_sdk/lib/core/Ajax.js
Normal file
@ -0,0 +1,72 @@
|
||||
import InterceptorManager from './InterceptorManager'
|
||||
import buildURL from '../helpers/buildURL'
|
||||
import mergeConfig from '../helpers/mergeConfig'
|
||||
import dispatchRequest from './dispatchRequest'
|
||||
import { detachCancel, dispatchCancel, interceptCancel } from './handleCancel'
|
||||
import defaults, { METHOD } from '../defaults'
|
||||
import { forEach, merge } from '../utils'
|
||||
|
||||
export default function Ajax(defaultConfig) {
|
||||
// 挂载当前实例配置
|
||||
ajax.config = Object.freeze(
|
||||
typeof defaultConfig === 'object' ? merge(defaultConfig) : defaultConfig
|
||||
)
|
||||
|
||||
// 挂载全局默认配置引用
|
||||
ajax.defaults = defaults
|
||||
|
||||
// 挂载拦截器
|
||||
ajax.interceptors = {
|
||||
request: new InterceptorManager(),
|
||||
response: new InterceptorManager()
|
||||
}
|
||||
|
||||
// 挂载获取实例请求地址方法
|
||||
ajax.getURL = async function getURL(config) {
|
||||
const combineConfig = await mergeConfig(defaults, defaultConfig, config)
|
||||
return buildURL(combineConfig).replace(/^\?/, '')
|
||||
}
|
||||
|
||||
// 挂载对应的 method 方法
|
||||
forEach(METHOD, method => {
|
||||
ajax[method] = function methodAjax(url, data, config) {
|
||||
if (typeof url === 'string') return ajax(url, data, { ...config, method })
|
||||
return ajax({ ...url, method })
|
||||
}
|
||||
})
|
||||
|
||||
function ajax(url, data, config) {
|
||||
const newConfig = typeof url === 'string' ? { ...config, url, data } : { ...url }
|
||||
|
||||
// 声明 Promise 链
|
||||
const chain = [dispatchRequest, dispatchCancel]
|
||||
|
||||
// 将请求拦截遍历添加到链前面
|
||||
ajax.interceptors.request.forEach(
|
||||
({ fulfilled, rejected }) => chain.unshift(fulfilled, rejected),
|
||||
true
|
||||
)
|
||||
|
||||
// 将响应拦截遍历添加到链后面
|
||||
ajax.interceptors.response.forEach(
|
||||
({ fulfilled, rejected }) => chain.push(fulfilled, interceptCancel(rejected)),
|
||||
false
|
||||
)
|
||||
|
||||
// 先执行获取 config 请求配置
|
||||
chain.unshift(config => mergeConfig(defaults, defaultConfig, config), undefined)
|
||||
|
||||
// 处理发起请求前的错误数据
|
||||
chain.push(undefined, detachCancel)
|
||||
|
||||
// 创建请求Promise,后面遍历链将链上方法传递到then回调
|
||||
let request = Promise.resolve(newConfig)
|
||||
while (chain.length) {
|
||||
request = request.then(chain.shift(), chain.shift())
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
return ajax
|
||||
}
|
32
uni_modules/uni-ajax/js_sdk/lib/core/InterceptorManager.js
Normal file
32
uni_modules/uni-ajax/js_sdk/lib/core/InterceptorManager.js
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 拦截器类
|
||||
*/
|
||||
export default class InterceptorManager {
|
||||
handlers = []
|
||||
|
||||
use(fulfilled, rejected) {
|
||||
this.handlers.push({
|
||||
fulfilled,
|
||||
rejected
|
||||
})
|
||||
return this.handlers.length - 1
|
||||
}
|
||||
|
||||
eject(id) {
|
||||
if (this.handlers[id]) {
|
||||
this.handlers[id] = null
|
||||
}
|
||||
}
|
||||
|
||||
forEach(fn, reverse = false) {
|
||||
if (reverse) {
|
||||
for (let i = this.handlers.length - 1; i >= 0; i--) {
|
||||
this.handlers[i] !== null && fn(this.handlers[i])
|
||||
}
|
||||
} else {
|
||||
for (let i = 0, l = this.handlers.length; i < l; i++) {
|
||||
this.handlers[i] !== null && fn(this.handlers[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
uni_modules/uni-ajax/js_sdk/lib/core/dispatchRequest.js
Normal file
29
uni_modules/uni-ajax/js_sdk/lib/core/dispatchRequest.js
Normal file
@ -0,0 +1,29 @@
|
||||
import buildURL from '../helpers/buildURL'
|
||||
import isCallback from '../helpers/isCallback'
|
||||
import { forEach, isPlainObject, merge } from '../utils'
|
||||
import { HEADER } from '../defaults'
|
||||
|
||||
/** 派发请求方法 */
|
||||
export default function dispatchRequest(config) {
|
||||
// 拼接 url
|
||||
config.url = buildURL(config)
|
||||
|
||||
// 请求方法转大写
|
||||
config.method = (config.method || 'get').toUpperCase()
|
||||
|
||||
// 调整 header 优先级
|
||||
config.header = merge(
|
||||
config.header.common,
|
||||
config.header[config.method.toLowerCase()],
|
||||
config.header
|
||||
)
|
||||
|
||||
// 清除多余的请求头
|
||||
forEach(HEADER, h => isPlainObject(config.header[h]) && delete config.header[h])
|
||||
|
||||
// 清除回调函数
|
||||
forEach(config, (val, key) => isCallback(key) && delete config[key])
|
||||
|
||||
// 执行请求方法
|
||||
return config.adapter(config)
|
||||
}
|
35
uni_modules/uni-ajax/js_sdk/lib/core/handleCancel.js
Normal file
35
uni_modules/uni-ajax/js_sdk/lib/core/handleCancel.js
Normal file
@ -0,0 +1,35 @@
|
||||
const CANCEL = Symbol('$$cancel')
|
||||
|
||||
function hasCancel(target) {
|
||||
return target === null || target === undefined
|
||||
? false
|
||||
: Object.prototype.hasOwnProperty.call(target, CANCEL)
|
||||
}
|
||||
|
||||
/**
|
||||
* 派发请求拒绝方法,处理发起请求前错误,取消执行请求,并防止进入响应拦截器
|
||||
* @param {*} reason 错误原因
|
||||
* @returns {Promise} 封装了 CANCEL 的失败对象
|
||||
*/
|
||||
export function dispatchCancel(reason) {
|
||||
return Promise.reject({ [CANCEL]: reason })
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截失败对象
|
||||
* @param {Function} rejected 响应错误拦截器
|
||||
*/
|
||||
export function interceptCancel(rejected) {
|
||||
// 判断发起请求前是否发生错误,如果发生错误则不执行后面的响应错误拦截器
|
||||
return (
|
||||
rejected && (response => (hasCancel(response) ? Promise.reject(response) : rejected(response)))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分离失败对象
|
||||
* @param {*} response 封装了 CANCEL 的失败对象
|
||||
*/
|
||||
export function detachCancel(error) {
|
||||
return Promise.reject(hasCancel(error) ? error[CANCEL] : error)
|
||||
}
|
16
uni_modules/uni-ajax/js_sdk/lib/defaults.js
Normal file
16
uni_modules/uni-ajax/js_sdk/lib/defaults.js
Normal file
@ -0,0 +1,16 @@
|
||||
import adapter from './adapters/http'
|
||||
import { forEach } from './utils'
|
||||
|
||||
export const METHOD = ['get', 'post', 'put', 'delete', 'connect', 'head', 'options', 'trace']
|
||||
export const HEADER = ['common', ...METHOD]
|
||||
|
||||
const defaults = {
|
||||
adapter,
|
||||
header: {},
|
||||
method: 'GET',
|
||||
validateStatus: statusCode => statusCode >= 200 && statusCode < 300
|
||||
}
|
||||
|
||||
forEach(HEADER, h => (defaults.header[h] = {}))
|
||||
|
||||
export default defaults
|
83
uni_modules/uni-ajax/js_sdk/lib/helpers/buildURL.js
Normal file
83
uni_modules/uni-ajax/js_sdk/lib/helpers/buildURL.js
Normal file
@ -0,0 +1,83 @@
|
||||
import { forEach, isArray } from '../utils'
|
||||
|
||||
/**
|
||||
* 根据 baseURL 和 url 拼接
|
||||
* @param {string} baseURL 请求根地址
|
||||
* @param {string} relativeURL 请求参数地址
|
||||
* @returns {string} 拼接后的地址
|
||||
*/
|
||||
function combineURL(baseURL = '', relativeURL = '') {
|
||||
// 判断是否 http:// 或 https:// 开头
|
||||
if (/^https?:\/\//.test(relativeURL)) return relativeURL
|
||||
// 去除 baseURL 结尾斜杠,去除 relativeURL 开头斜杠,再判断拼接
|
||||
return relativeURL ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL
|
||||
}
|
||||
|
||||
function encode(val) {
|
||||
return encodeURIComponent(val)
|
||||
.replace(/%3A/gi, ':')
|
||||
.replace(/%24/g, '$')
|
||||
.replace(/%2C/gi, ',')
|
||||
.replace(/%20/g, '+')
|
||||
.replace(/%5B/gi, '[')
|
||||
.replace(/%5D/gi, ']')
|
||||
}
|
||||
|
||||
function querystring(url, params) {
|
||||
let query
|
||||
|
||||
const parts = []
|
||||
forEach(params, (val, key) => {
|
||||
if (val === null || typeof val === 'undefined') return
|
||||
|
||||
if (isArray(val)) key = key + '[]'
|
||||
else val = [val]
|
||||
|
||||
forEach(val, v => {
|
||||
if (v !== null && typeof v === 'object') {
|
||||
v = JSON.stringify(v)
|
||||
}
|
||||
parts.push(encode(key) + '=' + encode(v))
|
||||
})
|
||||
})
|
||||
query = parts.join('&')
|
||||
|
||||
if (query) {
|
||||
const hashmarkIndex = url.indexOf('#')
|
||||
hashmarkIndex !== -1 && (url = url.slice(0, hashmarkIndex))
|
||||
url += (url.indexOf('?') === -1 ? '?' : '&') + query
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 baseURL、url、params query 编译请求URL
|
||||
* @returns {string} 处理后的地址
|
||||
*/
|
||||
export default function buildURL({ baseURL, url: relativeURL, params, query } = {}) {
|
||||
let url = combineURL(baseURL, relativeURL)
|
||||
|
||||
if (!params && !query) {
|
||||
return url
|
||||
}
|
||||
|
||||
if (params) {
|
||||
if (/\/:/.test(url)) {
|
||||
// 是否是 params 参数地址,并对应设置
|
||||
forEach(params, (val, key) => {
|
||||
url = url.replace(`/:${key}`, `/${encode(String(val))}`)
|
||||
})
|
||||
} else if (!query) {
|
||||
// 兼容旧的 params 属性设置 query
|
||||
url = querystring(url, params)
|
||||
}
|
||||
}
|
||||
|
||||
// 设置 query 参数
|
||||
if (query) {
|
||||
url = querystring(url, query)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
8
uni_modules/uni-ajax/js_sdk/lib/helpers/isCallback.js
Normal file
8
uni_modules/uni-ajax/js_sdk/lib/helpers/isCallback.js
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* 判断参数是否含有回调参数 success / fail / complete 之一
|
||||
* @param {string} field 参数的 Key 值字符串
|
||||
* @returns {boolean} 返回判断值
|
||||
*/
|
||||
export default function isCallback(field) {
|
||||
return ['success', 'fail', 'complete'].includes(field)
|
||||
}
|
41
uni_modules/uni-ajax/js_sdk/lib/helpers/mergeConfig.js
Normal file
41
uni_modules/uni-ajax/js_sdk/lib/helpers/mergeConfig.js
Normal file
@ -0,0 +1,41 @@
|
||||
import { assign, forEach } from '../utils'
|
||||
|
||||
/**
|
||||
* 深度合并,且不合并 undefined 值
|
||||
* @param {object} obj1 前对象
|
||||
* @param {object} obj2 后对象
|
||||
* @returns {object} 合并后的对象
|
||||
*/
|
||||
function merge(obj1 = {}, obj2 = {}) {
|
||||
const obj = {}
|
||||
|
||||
const objKeys = Object.keys({ ...obj1, ...obj2 })
|
||||
|
||||
forEach(objKeys, prop => {
|
||||
if (obj2[prop] !== undefined) {
|
||||
obj[prop] = assign(obj1[prop], obj2[prop])
|
||||
} else if (obj1[prop] !== undefined) {
|
||||
obj[prop] = assign(undefined, obj1[prop])
|
||||
}
|
||||
})
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并请求配置
|
||||
* @param {...object|function} args 请求配置
|
||||
* @returns {object} 合并后的请求配置
|
||||
*/
|
||||
export default async function mergeConfig(...args) {
|
||||
let config = {}
|
||||
|
||||
for (let i = 0, l = args.length; i < l; i++) {
|
||||
const current = typeof args[i] === 'function' ? await args[i]() : args[i]
|
||||
config = merge(config, current)
|
||||
}
|
||||
|
||||
config.method = config.method.toUpperCase()
|
||||
|
||||
return config
|
||||
}
|
77
uni_modules/uni-ajax/js_sdk/lib/utils.js
Normal file
77
uni_modules/uni-ajax/js_sdk/lib/utils.js
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 获取值的原始类型字符串,例如 [object Object]
|
||||
*/
|
||||
const _toString = Object.prototype.toString
|
||||
|
||||
/**
|
||||
* 判断是否为数组
|
||||
* @param {*} val 要判断的值
|
||||
* @returns {boolean} 返回判断结果
|
||||
*/
|
||||
export function isArray(val) {
|
||||
return _toString.call(val) === '[object Array]'
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为普通对象
|
||||
* @param {*} val 要判断的值
|
||||
* @returns {boolean} 返回判断结果
|
||||
*/
|
||||
export function isPlainObject(val) {
|
||||
return _toString.call(val) === '[object Object]'
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历
|
||||
* @param {object|array} obj 要迭代的对象
|
||||
* @param {function} fn 为每个项调用的回调
|
||||
*/
|
||||
export function forEach(obj, fn) {
|
||||
if (obj === null || obj === undefined) return
|
||||
if (typeof obj !== 'object') obj = [obj]
|
||||
if (isArray(obj)) {
|
||||
for (let i = 0, l = obj.length; i < l; i++) {
|
||||
fn.call(null, obj[i], i, obj)
|
||||
}
|
||||
} else {
|
||||
for (const k in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, k)) {
|
||||
fn.call(null, obj[k], k, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象深合并
|
||||
* @param {...object} args 对象
|
||||
* @returns {object} 合并后的对象
|
||||
*/
|
||||
export function merge(...args) {
|
||||
const result = {}
|
||||
for (let i = 0, l = args.length; i < l; i++) {
|
||||
if (isPlainObject(args[i])) {
|
||||
forEach(args[i], (val, key) => {
|
||||
result[key] = assign(result[key], val)
|
||||
})
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并分配到目标对象
|
||||
* @param {*} target 目标对象
|
||||
* @param {*} source 源对象
|
||||
* @returns {*} 目标对象
|
||||
*/
|
||||
export function assign(target, source) {
|
||||
if (isPlainObject(target) && isPlainObject(source)) {
|
||||
return merge(target, source)
|
||||
} else if (isPlainObject(source)) {
|
||||
return merge({}, source)
|
||||
} else if (isArray(source)) {
|
||||
return source.slice()
|
||||
}
|
||||
return source
|
||||
}
|
Reference in New Issue
Block a user