当前位置: 主页 > 日志 > 个人日记 > 文章

前端基于uniapp完善的请求封装适用于(微信小程序,vue,管理后台,uniapp)

发布时间: 2023-05-08 17:15:24 作者: 王乐园 浏览次数: 332

以上代码是使用uni-app框架封装的一个通用请求方法 request() 。它包含了请求拦截器、响应拦截器、请求重试、加密/解密、缓存、文件上传等功能。

代码如下:

import cryptoJS from '@/utils/crypto-js.min.js'
const BASE_URL = 'http://example.com/api/';
let requestCount = 0;
const DEFAULT_OPTIONS = {
	url: '',
	method: 'GET',
	data: {},
	header: {
		'content-type': 'application/json'
	},
	timeout: 10000, // 请求超时时间,单位毫秒
	retry: 0, // 请求重试次数
	encrypt: false, // 是否加密
	cache: false, // 是否缓存
	cacheTime: 60000, // 缓存时间,单位毫秒
	cancelToken: null // 取消请求的 token
};
export default function request(options = {}) {
	options = Object.assign({}, DEFAULT_OPTIONS, options);
	// 请求次数加1
	requestCount++;
	// 请求拦截器
	uni.showLoading({
		title: '加载中'
	});
	return new Promise((resolve, reject) => {
			let retryCount = 0;
			const doRequest = () => {
				// 取消请求
				if (options.cancelToken) {
					options.cancelToken.promise.then(cancel => {
						reject(cancel);
					});
				}
				const requestParams = {
					url: BASE_URL + options.url,
					method: options.method,
					data: options.data,
					header: options.header
				};
				// 加密处理
				if (options.encrypt) {
					const timestamp = Date.now();
					const key = 'example'; // 加密的秘钥
					const plainText = JSON.stringify(requestParams.data) + timestamp;
					const cipherText = cryptoJS.AES.encrypt(plainText, key).toString();
					requestParams.data = {
						data: cipherText,
						timestamp
					};
				}
				// 缓存处理
				if (options.cache) {
					const cacheKey = options.url + JSON.stringify(requestParams.data);
					const cachedData = uni.getStorageSync(cacheKey);
					if (cachedData && Date.now() - cachedData.timestamp < options.cacheTime) {
						resolve(cachedData.data);
						return;
					}
				}
				// 文件上传处理
				if (options.files) {
					requestParams.formData = options.data;
					for (let i = 0; i < options.files.length; i++) {
						const file = options.files[i];
						requestParams.filePath = file.path;
						requestParams.name = file.name;
					}
				}

				uni.request({
					...requestParams,
					success: res => {
						// 响应拦截器
						uni.hideLoading();
						if (res.statusCode === 200) {
							// 解密处理
							let data = res.data;
							if (options.encrypt) {
								const key = 'example'; // 解密的秘钥
								const decryptedData = cryptoJS.AES.decrypt(data.data, key);
								data = JSON.parse(decryptedData.toString(cryptoJS.enc.Utf8));
							}
							// 缓存处理
							if (options.cache) {
								const cacheKey = options.url + JSON.stringify(requestParams.data);
								uni.setStorageSync(cacheKey, {
									data,
									timestamp: Date.now()
								});
							}
							resolve(data);
						} else {
							reject(new Error(res.statusCode));
						}
					},
					fail: err => {
						// 错误处理
						uni.hideLoading();
						if (retryCount < options.retry) {
							retryCount++;
							doRequest();
						} else {
							reject(err);
						}
					},
					complete: () => {
						// 请求次数减1
						requestCount--;
						// 当所有请求都完成时,关闭Loading
						if (requestCount === 0) {
							uni.hideLoading();
						}
					}
				});
			};
			// 发起请求前调用请求拦截器
			let interceptor = {
				request: config => config,
				response: res => res
			};
			if (typeof options.interceptor === 'function') {
				interceptor = options.interceptor(interceptor);
			}
			const modifiedOptions = interceptor.request(options);
			doRequest(modifiedOptions);
			// 请求超时处理
			setTimeout(() => {
				if (requestCount > 0) {
					uni.hideLoading();
					reject(new Error('Request timeout'));
				}
			}, options.timeout);
		})
		.then(res => {
			// 在响应成功后调用响应拦截器
			let interceptor = {
				request: config => config,
				response: res => res
			};
			if (typeof options.interceptor === 'function') {
				interceptor = options.interceptor(interceptor);
			}
			return interceptor.response(res);
		});
}
// 取消请求的 token
export function createCancelToken() {
	const source = {
		token: null,
		cancel: null,
		promise: null
	};
	source.promise = new Promise((resolve, reject) => {
		source.cancel = reject;
	});
	source.token = {
		source,
		cancel: source.cancel
	};
	return source.token;
}

// 请求示例
/*
1. 加密请求示例
import request from '@/utils/request';

request({
  url: 'package/create',
  method: 'POST',
  data: {
    name: 'test package',
    description: 'This is a test package',
    price: 10,
    quantity: 100
  },
  encrypt: true, // 启用加密
}).then(res => {
  console.log(res);
}).catch(err => {
  console.error(err);
});

2. 带请求拦截器和响应拦截器的请求示例:
import request from '@/utils/request';

request({
  url: 'package/create',
  method: 'POST',
  data: {
    name: 'test package',
    description: 'This is a test package',
    price: 10,
    quantity: 100
  },
  interceptor: function (interceptor) {
    // 请求拦截器
    interceptor.request = config => {
      // 在这里可以修改请求参数,例如添加统一的token
      config.data.token = 'your token';
      return config;
    };
    // 响应拦截器
    interceptor.response = res => {
      // 在这里可以对响应数据进行处理,例如统一处理错误提示
      if (res.code !== 200) {
        console.error('请求错误:' + res.msg);
      }
      return res;
    };
    return interceptor;
  }
}).then(res => {
  console.log(res);
}).catch(err => {
  console.error(err);
});

3. 文件上传示例:
import request from '@/utils/request';

request({
  url: 'package/upload',
  method: 'POST',
  data: {
    name: 'test package',
    description: 'This is a test package',
    price: 10,
    quantity: 100
  },
  files: [
    {
      path: '/path/to/your/file', // 本地文件路径,可以通过uni.chooseImage()等方法获取
      name: 'file' // 文件对应的key,后台接收的参数名
    }
  ],
}).then(res => {
  console.log(res);
}).catch(err => {
  console.error(err);
});
4. createCancelToken() 方法的主要作用是生成一个可以用于取消请求的token。这个方法返回一个对象,其中包含一个 source 属性(包含promise和cancel方法)和一个 cancel 方法。当你需要取消一个请求时,可以调用这个 cancel 方法。 */


本站文章均为原创,欢迎转载,转载请以链接形式注明出处

本文地址: