uniapp封装请求及loading合并

520 阅读2分钟

请求封装

//引入方法
import RequestManager from '@/utils/requestManager.js'
import Vue from 'vue'
const manager = new RequestManager() //创建
//请求数量
let loadingRequestCount = 0
const baseRequest = async (url, method, data = {}, herder, loading = true) => {
	let header = {}
	let token = uni.getStorageSync('access_token');
	Object.assign(header, {
		Authorization: 'Bearer ' + token
	})
	// 生成唯一ID, 如果返回false 代表重复请求
	let requestId = manager.generateId(method, url, data)
	if (!requestId) {
		console.log('重复请求')
		return false
	}
	return new Promise((reslove, reject) => {
		// 开启loading
		loading && showLoading()
		uni.request({
			url: url,
			method: method || 'GET',
			header: header,
			timeout: 10000,
			data: data || {},
			success: (successData) => {
				const res = successData.data
				if (successData.statusCode == 200 || successData.statusCode == 201 ||
					successData.statusCode == 204) {
					reslove(res)
					// 业务逻辑
					
				} else {
					uni.showToast({
						title: res.error_description,
						icon: 'none',
						duration: 2000
					});
					reject(res)
				}
			},
			fail: (msg) => {
				uni.showToast({
					title: successData.successData,
					icon: 'none',
					duration: 2000
				});
				reject(msg)
			},
			complete: () => {
				// 请求完成,清除当前请求的唯一ID
				manager.deleteById(requestId)
				// 关闭loading
				// 响应拦截进来隐藏loading效果,此处采用延时处理是合并loading请求效果,避免多次请求loading关闭又开启合并loading请求效果 避免重复请求
				setTimeout(() => {
					hideLoading()
				}, 200);

			},
		})
	})
}
//请求方法
const request = {}
const requestArr = ['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect']
requestArr.forEach((method) => {
	request[method] = (api, data, loading) => baseRequest(api, method, data, loading)
})


//loading封装
const showLoading = () => {
	if (loadingRequestCount === 0) {
		uni.showLoading({
			title: 'loading'
		})
	}
	loadingRequestCount++
}
const hideLoading = () => {
	if (loadingRequestCount <= 0) return
	loadingRequestCount--
	if (loadingRequestCount === 0) {
		Vue.nextTick(() => { //以服务的方式调用的 Loading 需要异步关闭
			uni.hideLoading()
		})
	}
}

export default request

重复请求判断方法

class RequestManager {
	constructor() {
		this.idMap = new Map()
	}
	/**
	 * 生成唯一ID的方法
	 * @param {string} method - 请求方法
	 * @param {string} url - 请求URL
	 * @param {object} params - 请求参数
	 * @returns {string} - 生成的唯一ID
	 */
	generateUniqueId(method, url, params) {
		const idString = `${method}-${url}-${this.serializeObject(params)}`
		let id = 0;
		for (let i = 0; i < idString.length; i++) {
			id = ((id << 5) - id) + idString.charCodeAt(i)
			id |= 0;
		}
		return id.toString()
	}

	/**
	 * 序列化对象为字符串
	 * @param {object} obj - 要序列化的对象
	 * @returns {string} - 序列化后的字符串
	 */
	serializeObject(obj) {
		const keys = Object.keys(obj).sort()
		const serializedObj = {}
		for (let key of keys) {
			const value = obj[key]
			if (value !== null && typeof value === 'object') {
				serializedObj[key] = this.serializeObject(value)
			} else {
				serializedObj[key] = value
			}
		}
		return JSON.stringify(serializedObj)
	}
	/**
	 * 根据ID删除map对象中的请求信息
	 * @param {string} id - 要删除的唯一ID
	 */
	deleteById(id) {
		this.idMap.delete(id)
	}
	/**
	 * 生成唯一ID,并将ID和请求信息存储到map对象中
	 * @param {string} method - 请求方法
	 * @param {string} url - 请求URL
	 * @param {object} params - 请求参数
	 * @returns {string|boolean} - 生成的唯一ID,如果存在相同id则返回false 
	 */
	generateId(method, url, params) {
		const id = this.generateUniqueId(method, url, params)
		if (this.idMap.has(id)) {
			return false
		}
		this.idMap.set(id, {
			method,
			url,
			params
		})
		return id
	}

}

export default RequestManager

path请求路径示例

export const example = (url,data) => request.get(baseUrlE+"example"+url, data)

封装方法借鉴