123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- import EventEmitter from './EventEmitter'
- import merge from 'ts-deepmerge'
- import { getSign } from './util'
- const DEFAULT_CONFIG: EventRequestConfig = {
- maxConcurrent: 10,
- timeout: 0,
- header: {},
- dataType: 'json',
- baseUrl: '',
- }
- type HttpHeader = Record<string, string>
- interface EventRequestConfig {
- maxConcurrent: number
- /** 过期时间(毫秒) */
- timeout: number
- header: HttpHeader
- dataType: 'json' | '其他'
- baseUrl: string
- }
- interface HttpRequestConfig {
- url: string
- method: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT' | undefined
- data: Object | string
- header: HttpHeader
- dataType: 'json' | '其他'
- }
- interface RequestJob {
- config: HttpRequestConfig
- resolve(data: any): void
- reject(data: any): void
- response?: any
- }
- interface HttpRequestCallBack {
- success(data: HttpResponse): void
- fail(err: HttpRequestErr): void
- complete(): void
- }
- interface HttpRequestErr {
- /** 错误信息 */
- errMsg: string
- /** 需要基础库: `2.24.0`
- *
- * errno 错误码,错误码的详细说明参考 [Errno错误码](https://developers.weixin.qq.com/miniprogram/dev/framework/usability/PublicErrno.html) */
- errno: number
- }
- interface HttpResponse<T = any> {
- timeout?: string
- data: T
- errMsg: string
- statusCode: number
- header: Record<string, string>
- }
- type RequestInterceptorCallback = (config: HttpRequestConfig) => boolean
- type ResponseInterceptorCallback = (
- config: HttpRequestConfig,
- response: HttpResponse,
- ) => Promise<any>
- class EventRequest extends EventEmitter {
- private config: EventRequestConfig
- private queue: RequestJob[] = []
- private runningTask: number = 0
- private maxConcurrent = DEFAULT_CONFIG.maxConcurrent
- private requestInterceptor: RequestInterceptorCallback = () => true
- private responseInterceptor: ResponseInterceptorCallback = (_, rsp) =>
- new Promise((resolve) => resolve(rsp.data))
- constructor(_config?: Partial<EventRequestConfig>) {
- super()
- if (_config) {
- this.config = merge({}, DEFAULT_CONFIG, _config)
- } else {
- this.config = DEFAULT_CONFIG
- }
- this.maxConcurrent = this.config.maxConcurrent
- }
- private next(): void {
- const queue = this.queue
- if (!queue.length || this.runningTask >= this.maxConcurrent) return
- const entity = queue.shift()!
- const httpConfig = entity.config
- const { requestInterceptor, responseInterceptor } = this
- if (requestInterceptor.call(this, httpConfig) !== true) {
- let response: HttpResponse = {
- data: null,
- errMsg: `Request Interceptor: Request can\'t pass the Interceptor`,
- statusCode: 0,
- header: {},
- }
- entity.reject(response)
- return
- }
- this.emit('request', httpConfig)
- this.runningTask = this.runningTask + 1
- let timer = -1
- let aborted: boolean = false
- let finished: boolean = false
- const callBack: HttpRequestCallBack = {
- success: (res: HttpResponse): void => {
- if (aborted) return
- finished = true
- timer && clearTimeout(timer)
- entity.response = res
- this.emit('success', httpConfig, res)
- responseInterceptor
- .call(this, httpConfig, res)
- .then((rsp) => {
- entity.resolve(rsp)
- })
- .catch((err) => {
- entity.reject(err)
- })
- },
- fail: (err: HttpRequestErr): void => {
- if (aborted) return
- finished = true
- timer && clearTimeout(timer)
- entity.response = err
- this.emit('fail', httpConfig, err)
- entity.reject(err)
- },
- complete: () => {
- if (aborted) return
- this.emit('complete', httpConfig, entity.response)
- this.next()
- this.runningTask = this.runningTask - 1
- },
- }
- const requestConfig = Object.assign(httpConfig, callBack)
- const task = wx.request(requestConfig)
- if (this.config.timeout > 0) {
- timer = setTimeout(() => {
- if (!finished) {
- aborted = true
- entity.reject({
- timeout: '访问超时',
- })
- task && task.abort()
- this.next()
- }
- }, this.config.timeout)
- }
- }
- request<T = any>(
- method: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT',
- url: string,
- data: Object | string = '',
- header: HttpHeader = {},
- dataType?: 'json' | '其他',
- ): Promise<T> {
- const token = getSign()
- const language = 'zh-Hans'
- let authHeader = {}
- if (token != null) {
- authHeader = {
- Authorization: `Bearer ${token}`,
- '.AspNetCore.Culture': `c=${language}|uic=${language}`,
- Accept: 'application/json',
- } as Record<string, any>
- }
- const config: HttpRequestConfig = {
- method,
- url: this.config.baseUrl + url,
- data,
- header: { ...header, ...this.config.header, ...authHeader },
- dataType: dataType || this.config.dataType,
- }
- return new Promise((resolve, reject) => {
- const entity: RequestJob = { config, resolve, reject, response: null }
- this.queue.push(entity)
- this.next()
- })
- }
- head<T>(url: string, data?: Object | string, header?: HttpHeader, dataType?: 'json' | '其他') {
- return this.request<T>('HEAD', url, data, header, dataType)
- }
- options<T>(url: string, data?: Object | string, header?: HttpHeader, dataType?: 'json' | '其他') {
- return this.request<T>('OPTIONS', url, data, header, dataType)
- }
- get<T>(url: string, data?: Object | string, header?: HttpHeader, dataType?: 'json' | '其他') {
- return this.request<T>('GET', url, data, header, dataType)
- }
- post<T>(url: string, data?: Object | string, header?: HttpHeader, dataType?: 'json' | '其他') {
- return this.request<T>('POST', url, data, header, dataType)
- }
- put<T>(url: string, data?: Object | string, header?: HttpHeader, dataType?: 'json' | '其他') {
- return this.request<T>('PUT', url, data, header, dataType)
- }
- ['delete']<T>(
- url: string,
- data?: Object | string,
- header?: HttpHeader,
- dataType?: 'json' | '其他',
- ) {
- return this.request<T>('DELETE', url, data, header, dataType)
- }
- trace<T>(url: string, data?: Object | string, header?: HttpHeader, dataType?: 'json' | '其他') {
- return this.request<T>('TRACE', url, data, header, dataType)
- }
- connect<T>(url: string, data?: Object | string, header?: HttpHeader, dataType?: 'json' | '其他') {
- return this.request<T>('CONNECT', url, data, header, dataType)
- }
- setRequestInterceptor(interceptor: (config: HttpRequestConfig) => boolean) {
- this.requestInterceptor = interceptor
- return this
- }
- setResponseInterceptor(
- interceptor: (config: HttpRequestConfig, response: HttpResponse) => Promise<any>,
- ) {
- this.responseInterceptor = interceptor
- return this
- }
- clean(): void {
- this.queue = []
- }
- }
- export default EventRequest
|