JavaScript/TypeScript 동시 요청 제어를 위한 예제 코드
4918 단어 JavaScript동시 요청 제어
장면
가령 10개의 요청이 있지만 가장 큰 병발 수량은 5개이며 요청 결과를 받아야 한다고 가정하면 간단한 병발 요청 제어이다
시뮬레이션
set Timeout을 이용해서 간단한 모방 요청을 실행합니다.
let startTime = Date.now();
const timeout = (timeout: number, ret: number) => {
return (idx?: any) =>
new Promise((resolve) => {
setTimeout(() => {
const compare = Date.now() - startTime;
console.log(`At ${Math.floor(compare / 100)}00 return`, ret);
resolve(idx);
}, timeout);
});
};
const timeout1 = timeout(1000, 1);
const timeout2 = timeout(300, 2);
const timeout3 = timeout(400, 3);
const timeout4 = timeout(500, 4);
const timeout5 = timeout(200, 5);
이렇게 요청을 시뮬레이션하면 본질은 Promise병발 제어가 없을 때.
const run = async () => {
startTime = Date.now();
await Promise.all([
timeout1(),
timeout2(),
timeout3(),
timeout4(),
timeout5(),
]);
};
run();
At 200 return 5
At 300 return 2
At 400 return 3
At 500 return 4
At 1000 return 1
출력이 52 3 4 1입니다. 타임아웃으로 출력이 됩니다.병발 조건
같은 시간의 최대 병렬 수가 2이라고 가정하고 클래스를 만듭니다
class Concurrent {
private maxConcurrent: number = 2;
constructor(count: number = 2) {
this.maxConcurrent = count;
}
}
첫 번째 병렬 제어
생각해 보세요. 최대 병발수에 따라 Promise 그룹을 나누고, Promise가fulfilled될 때 제거하고pending 상태의 Promise를 추가합니다.Promise.레이스가 이 수요를 충족시킬 수 있어요.
class Concurrent {
private maxConcurrent: number = 2;
constructor(count: number = 2) {
this.maxConcurrent = count;
}
public async useRace(fns: Function[]) {
const runing: any[] = [];
// , Promise
// Promise , Promise resolve
for (let i = 0; i < this.maxConcurrent; i++) {
if (fns.length) {
const fn = fns.shift()!;
runing.push(fn(i));
}
}
const handle = async () => {
if (fns.length) {
const idx = await Promise.race<number>(runing);
const nextFn = fns.shift()!;
// Promise,
runing.splice(idx, 1, nextFn(idx));
handle();
} else {
// , Promise , Promise.all
await Promise.all(runing);
}
};
handle();
}
}
const run = async () => {
const concurrent = new Concurrent();
startTime = Date.now();
await concurrent.useRace([timeout1, timeout2, timeout3, timeout4, timeout5]);
};
At 300 return 2
At 700 return 3
At 1000 return 1
At 1200 return 5
At 1200 return 4
출력이 바뀌었음을 볼 수 있다. 왜 이러는지 분석해 보자. 최대 병발수 2//우선 1 2
1 1000MS가 필요합니다.
2 300MS 필요
2 실행 완료, 타임라인 300 제거 2 가입 3 실행 시작 3
3 400MS 실행 후 700 제거 3 가입 4 시작 4
4 500MS 필요
타임라인이 1000MS에 와서 1 실행 완료 제거 1 가입 5 실행 시작 5
타임라인이 1200MS에 이르러 4와 5가 동시에 실행되었다
두 번째 방안
await의 메커니즘을 이용할 수 있는 것도 사실 작은 기교이다
await 표현식은 현재 asyncfunction의 실행을 멈추고 Promise 처리가 끝날 때까지 기다립니다.Promise가 정상적으로 처리되면 리셋된resolve 함수 인자는await 표현식의 값으로 asyncfunction를 계속 실행합니다.
현재 병렬 수가 최대 병렬 수를 초과하면 새로운 Promise를 설정하고await, 다른 요청이 완료될 때,resolve, 제거 대기를 설정할 수 있습니다. 따라서 두 개의 상태를 추가해야 합니다. 현재 병렬 수, 그리고resolve라는 리셋 함수를 저장하는 수조
class Concurrent {
private maxConcurrent: number = 2;
private list: Function[] = [];
private currentCount: number = 0;
constructor(count: number = 2) {
this.maxConcurrent = count;
}
public async add(fn: Function) {
this.currentCount += 1;
//
if (this.currentCount > this.maxConcurrent) {
// wait Promise, resolve fulfilled
const wait = new Promise((resolve) => {
this.list.push(resolve);
});
// resolve ,
await wait;
}
//
await fn();
this.currentCount -= 1;
if (this.list.length) {
// resolve , , wait ,
const resolveHandler = this.list.shift()!;
resolveHandler();
}
}
}
const run = async () => {
const concurrent = new Concurrent();
startTime = Date.now();
concurrent.add(timeout1);
concurrent.add(timeout2);
concurrent.add(timeout3);
concurrent.add(timeout4);
concurrent.add(timeout5);
};
run();
At 300 return 2
At 700 return 3
At 1000 return 1
At 1200 return 5
At 1200 return 4
총결산
이 두 가지 방식은 모두 병행 제어를 실현할 수 있지만 실현 방식은 그다지 같지 않다. 주로 Promise에 의해 실현된다. 또한 실현 방식에서 이상한 상황을 고려하지 않는다. 이것은 스스로 덧붙일 수 있다.
JavaScript/TypeScript 병발 요청 제어의 예시 코드에 관한 이 글은 여기에 소개되었습니다. 더 많은 JavaScript 병발 요청 제어 내용은 저희 이전의 글을 검색하거나 아래의 관련 글을 계속 훑어보십시오. 앞으로 저희 글을 많이 사랑해 주십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
기초 정리 - 1문자 (String) 숫자 (Number) 불린 (Boolean) null undefined 심볼 (Symbol) 큰정수 (BigInt) 따옴표로 묶어 있어야 함 Not-A-Number - 숫자 데이터 / 숫자로 표...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.