处理高并发, 100 条数据,带宽为 10, 跑满带宽
Sunny-117 opened this issue · comments
Sunny commented
处理高并发, 100 条数据,带宽为 10, 跑满带宽
卷心菜汪 commented
function asyncPool(limit,dates,fn) {
let count = 0;
const exec = [];
const values = [];
const _asyncPool = () => {
if (count === dates.length) {
return Promise.resolve();
}
const item = dates[count++];
const p = Promise.resolve().then(()=>fn(item));
values.push(p);
const _p = p.then(()=>exec.splice(exec.indexOf(_p), 1));
exec.push(_p);
let next = Promise.resolve();
if (exec.length >= limit) {
next = Promise.race(exec);
}
return next.then(()=>_asyncPool());
}
return _asyncPool().then(()=>Promise.all(values));
}
zhuzhujian commented
async function asyncPool(poolLimit, array, iteratorFn) {
let poolList = [] // 并发队列
let ret = [] // 所有的任务
for(let i of array) {
let p = new Promise.resolve(iteratorFn(i)) // 添加Promise处理,统一处理非Promise的任务
ret.push(p)
let _p = p.then(() => { poolList.splice(poolList.indexOf(_p), 1)}) // 任务完成将任务推出队列
poolList.push(_p) // 将任务放到并发队列中去
if(poolList.length >= poolLimit) { // 当任务数达到并发上限
await Promise.race(poolList) // 等待队列中的任务完成
}
}
return Promise.all(ret) // 返回任务执行结果
}
flyflydogdog commented
function task() {
return new Promise(resolve => {
setTimeout(() => {
const timestamp = Date.now() / 1000 | 0
console.log(timestamp)
resolve(timestamp)
}, 1000)
})
}
async function concurrent(tasks, max = 10) {
const results = []
const poolList = new Set()
for (const task of tasks) {
if (poolList.size === max) {
await Promise.race(poolList).catch(console.log)
}
const p = task()
const cb = () => poolList.delete(p)
p.then(cb, cb)
poolList.add(p)
results.push(p)
}
return Promise.allSettled(results)
}
concurrent([task, task, task, task, task, task, task, task, task], 2)
.then(res => {
console.log(res)
})
zhuzhujian commented
你好,我已收到你的来信,我会尽快回复你的,谢谢!
jesi commented
// 处理高并发, 100 条数据,带宽为 10, 跑满带宽
const REQ_NUM = 100
const msg = new Array(REQ_NUM).fill('')
for (let i = 0; i < REQ_NUM; i++) {
msg[i] = `第${i + 1}条数据`
}
const getAxios = (msg) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(msg)
}, 1000 * Math.random())
})
}
const asyncProcess = async(limit = 10) => {
const tasks = []
const resArr = []
for (let i = 0; i < REQ_NUM; i++) {
const curTask = getAxios(msg[i]).then(res => {
resArr.push(res)
tasks.splice(tasks.indexOf(curTask), 1)
})
tasks.push(curTask)
if (tasks.length === limit) {
await Promise.race(tasks)
}
}
await Promise.allSettled(tasks)
return resArr
}
asyncProcess().then(res => {
console.log(res)
})
zhuzhujian commented
你好,我已收到你的来信,我会尽快回复你的,谢谢!
zhouzhikuan commented
//模拟请求
function mockRequest<T = unknown>(text: T): Promise<string> {
return new Promise((resolve) => {
const start = performance.now();
setTimeout(() => {
resolve(`${text}:${performance.now() - start}`);
}, 20 + Math.random() * 200);
});
}
type AsyncTask = () => Promise<unknown>;
// 请求任务
class RequestTask {
private runningTasks: Set<Promise<unknown>> = new Set();
private todoTasks: AsyncTask[] = [];
constructor(private config: { limit: number } = { limit: 10 }) {}
tryRun() {
if (this.runningTasks.size >= this.config.limit) {
Promise.race(this.runningTasks).then(() => this.tryRun());
} else if (this.todoTasks.length > 0) {
const task = this.todoTasks.shift()!;
const taskP = task().then(() => {
this.runningTasks.delete(taskP);
});
this.runningTasks.add(taskP);
}
}
run(task: AsyncTask): ReturnType<AsyncTask> {
return new Promise((resolve) => {
this.todoTasks.push(async () => {
const res = await task();
resolve(res);
});
this.tryRun();
});
}
}
const task = new RequestTask({limit:10});
Promise.all(
Array(100)
.fill(0)
.map((_, i) =>
task
.run(() => mockRequest(i))
.then((res) => {
console.log("child", res);
return res;
})
)
).then((res) => {
console.log("all", res);
});