前端请求并发控制

前端请求并发控制

介绍

在列表的导入导出时如果后台接口不支持多条传入并且后台控制了TPS(吞吐量)时可以使用这种方法

主要思想:

前端在请求数据时,先将所有的请求保存下来,在规定的并发内进行一个个的请求
包工头李四有20个搬砖工人,有一天,他有一大车的砖要搬,就把这些人叫来,动员大家搬砖,工人们一个个的干劲很高,一个个的在门口等着搬砖,早晨的砖不是那么烫手,车来了,大家开始搬砖。
问题出现了,门太小,一时间只能进去俩人,并且要等俩人出来才能让后面两个人进去,这样严重拖慢了赚钱速度,但是也不能直接把门给拆了,所以机灵的李四就让另外的18个人去张三的工地搬砖,那里的门大,砖多,这里就留两个搬就能完美的配合这个门

// 记录当前请求的次数
var count = 1;
// websocket请求连接
var connect = ()=> {
    return new Promise((resolve,reject)=>{
        let kstime = ""; // 开始时间
        let ljtime = ""; // 连接时间
        let fhtime = ""; // 返回时间
        // 连接本机
        let ws = new WebSocket("ws://192.168.8.216:8996");
        ws.onmessage = function (message) {
            fhtime = new Date().getTime();
            console.log("发送返回耗时:", fhtime - ljtime);
            console.log("总耗时:", fhtime - kstime);
            ws.close();
            console.log(message)
            resolve(message)
        };
        ws.onopen = function (time) {
            // 状态为1表示连接成功
            console.log("第" + count + "次");
            count++;
            console.log("正在连接中:");
            if (ws.readyState === 1) {
                ljtime = new Date().getTime();
                console.log("连接消耗时间:", ljtime - kstime);
                ws.send(count);
            }
        };
        ws.onclose = function (ms) {
            console.log(kstime, "开始创建");
            console.log(ljtime, "连接上");
            console.log(fhtime, "返回回来");
            console.log("-------------------------------------------------");
        };
        kstime = new Date().getTime();
    })
};

// 传入一个数字控制当前同时请求条数,只有在请求返回之后才能再次请求 验证数字
function validateCore(core) {
    if (core < 1) {
        throw new Error('parameter `core` must great than 0')
    }
}
class PromisePool {
	constructor(core) {
        validateCore(core)
        this.core = core
        this.isPause = false
    }
    core = 2 // 来几个人搬砖
    taskQueue = [] // 还有那么多砖要搬
    status = false // 是否正在搬砖
    isPause = false // 正在休息码
    // Promise状态
    statusPromise(){
        return Promise.resolve()
    }
    // 获取promise状态
    getStatusPromise() {
        return this.statusPromise
    }
    // 添加砖
    execute(feature) {
        this.taskQueue.push(feature)
        return this.resume()
    }
    // 砖拉走了
    async clear() {
        await this.pause()
        this.taskQueue.splice(0, this.taskQueue.length)
        return this.statusPromise
    }
    // 停下来吃顿午饭再说
    pause() {
        this.isPause = true
        return this.statusPromise
    }
    // 干活了
    resume() {
        this.isPause = false
        return this.beginExecute()
    }
    // 派多少人搬砖
    async setCore(core) {
    	// 不能来砖了,没人搬
        validateCore(core)
        if (this.status) {
        	// 来新人了,先停一下,让新人加入荣华富贵大家庭
            await this.pause()
            this.core = core
            // 大家一起搬砖喽
            return this.resume()
        } else {
            this.core = core
        }
    }
    // 大家在搬砖吗
    getstatus() {
        return this.status
    }
    // 开始搬砖
    beginExecute() {
        if (this.status) {
        	// 都已经搬砖了,继续就好了
            return
        }
        // 干活了(萌道)
        this.status = true
        const promiseArray = []
        for (let i = 0; i < this.core; i++) {
        	// 把需要砖都排好,来搬就行了
            promiseArray.push(this.doExecute())
        }
        // 奥里给
        this.statusPromise = Promise.all(promiseArray).finally(() => {
            this.status = false
        })
     return this.statusPromise
    }
    // 把砖一块块的放好
    doExecute(){
        return new Promise(resolve => {
        	// 取出第一块砖放好
            const executor = this.taskQueue.shift()
            // 拿到砖了,就搬过去
            if (executor) {
                let executorPromise
                if (typeof executor === 'function') {
                	// 是函数就执行一下
                    executorPromise =  Promise.resolve(executor())
                } else {
                	// 不是函数就过,只有一个工人的时候可以按照顺序,让一个人慢慢搬砖
                    executorPromise =  Promise.resolve(executor)
                }
                executorPromise.finally(() => {
                    resolve()
                })
            } else {
                resolve()
            }
        }).then(() => {
            if (this.isPause) {
            	// 通知回来搬砖的人,可以先休息一下
                return
            }
            // 后面还有砖,大家加油啊
            if (this.taskQueue.length > 0) {
                return this.doExecute()
            }
        })
     }
 }
let promisePool = new PromisePool(2)
for(let i = 0;i<10;i++){
    promisePool.execute(async ()=>{
        const data = await connect()
        console.log(i,data)
        return data
    })
}
setTimeout(()=>{
    promisePool.pause()
    console.log(promisePool)
},5000)

砖厂收到通知,用户想要定制一批砖,意见达成,双方慢慢聊(后台处理)

// 导入WebSocket 模块
const WebSocket = require("ws");
// 引用Server 类
const WebSocketServer = WebSocket.Server;
// 实例化
const ws = new WebSocketServer({port:8996});
ws.on('connection', function (ws) {
    console.log(`[SERVER] connection()`);
    ws.on('message', function (message) {
        console.log(`[SERVER] Received: ${message}`);
		var index = 0;
		var timer =	setInterval(()=>{
			index++;
			if(index==3){
				clearInterval(timer);
			}
			if(ws.readyState === 3){ // 断开连接
				return;
			}
			ws.send(`ECHO: ${message},${JSON.stringify(ws)}`, (err) => {
				if (err) {
					console.log(`[SERVER] error: ${err}`);
				}
			});
		},2000);
    })
});

结果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值