前端实现网络并发请求功能 typescript版

业务场景

该业务涉及到表格导入和切片上传等等,如果存在数据量较大情况下可能需要很久才能完成这个任务,那么客户一直去等待肯定是一件非常不友好的事情。所以我们需要优化并且利用到浏览器的特性可以同时发起多个请求,去减少等待时间。

方法实现有:完成进度、完成时间、区分请求成功数据和失败数据。

这里可以满足到一些基本需求,如果和你的业务还是相差甚远可以自行改造。

辅助函数
// 毫秒转换成时分秒
function nowTimeFu(milliseconds: number, joinStr: string = ':'):string {
	let seconds = Math.floor(milliseconds / 1000);
	let minutes = Math.floor(seconds / 60);
	let hours = Math.floor(minutes / 60);

	seconds %= 60;
	minutes %= 60;
	const padZero = (value: number) => String(value).padStart(2, '0');
	return [padZero(hours), padZero(minutes), padZero(seconds)].join(joinStr);
}
主要核心代码

注意这里用到的是axios请求,如果你没有下载axios就请先 npm install axios -save 

import axios, { AxiosRequestConfig, Method } from "axios";

type RequestResult<Success, Fail> = { success?: Success[], fail?: Fail[] };
interface RequestOptions {
	method?: Method;
	maxRequestNumber?: number;
	data: RequestData[];
}
export type RequestData = {
	url: string,
	body?: any
}
export function concurrencyRequest<Success = any, Fail = any>(
	{ data, maxRequestNumber = 5, method = 'GET' }: RequestOptions,
	progress?: (res: number) => void, // 进度条
	finalTime?: (str: string) => void // 最终用时
): Promise<RequestResult<Success, Fail>> {
	const startTime: number = new Date().getTime(); // 请求开始时间
	if (!Array.isArray(data)) return Promise.reject('urls must be an array');
	if (data.length === 0) {
		progress && progress(100);
		finalTime && finalTime(nowTimeFu((new Date().getTime() - startTime)));
		return Promise.resolve({ success: [], fail: [] });
	};
	return new Promise((resolve) => {
		let index: number = 0, // 记录每一项请求下标
			resultCount: number = 0; // 当前完成数量
		const successResult: Success[] = [], // 成功结果
			failResult: Fail[] = []; // 失败结果
		async function _request() {
			const item = data[index];
			index++;
			try {
                // -----这一块我建议可以自行使用封装好的网络请求-------
				const option: AxiosRequestConfig = {
					url: item.url,
					method,
				};
				switch (method) {
					case "GET":
					case "DELETE":
						option['params'] = item.body || {};
						break;
					case "POST":
					case "PATCH":
					case "PUT":
						option['data'] = item.body || {};
						break;
				}
				const { data } = await axios<Success>(option);
                // ------------------------------------------------
				successResult.push(data);
			} catch (error) {
				failResult.push(error as Fail);
			} finally {
				resultCount++;
				progress && progress(Math.floor(resultCount / data.length * 100)); // 实时监听进度结果
				if (resultCount === data.length) {
					resolve({ success: successResult, fail: failResult }); // 返回最终结果
					finalTime && finalTime(nowTimeFu((new Date().getTime() - startTime))); // 最终用时
				};
				if (index < data.length) _request();
			}
		}
		for (let i = 0; i < Math.min(data.length, maxRequestNumber); i++) {
			_request();
		}
	});
}
如何使用方法
   type Result = {
            message: string,
            status: string
        };
        function progress(num: number) {
            console.log(`进度为:${num}%`);
        }
        function finalTime(str: string) {
            console.log('最终用时: ', str);
        }
        (async () => {
           const data: RequestData[] = [];
            for (let index = 0; index < 100; index++) {
                if (index === 10) {
                    data.push({
                        url: `https://xx.ceo/api/breeds/image/random`,
                    })
                } else {
                    data.push({
                        url: `https://dog.ceo/api/breeds/image/random`,
                        body: { a: '11' }
                    })
                }
            }
            const response = await concurrencyRequest<Result, any>({ data }, progress, finalTime);
            console.log('response: ', response);
        })();

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值