반응형
목표
Iterator 객체를 생성하고, 반복 처리에 활용한다.
사용이유
여러 HTTP Request를 보내서 받은 stream 데이터를 사용자 입장에서 가시적으로 확인할 수 있도록 진행바가 필요했다.
구현
Set을 이용한 UniqueQueue
작업이 담긴 배열을 순차적으로 진행하고 진행 중인 작업 수가 최대치일 경우 보류하여 이후에 진행되도록 작업하였다.
class Worker {
private readonly works: Work[];
private readonly workQueue: UniqueQueue<Work>;
private readonly maxWorker = 60;
constructor(requests: WorkRequest[]) {
this.works = requests.map((r) => new Work(r));
this.workQueue = new UniqueQueue(this.works);
}
public work(work: Work) {
...
}
public async run() {
while (this.workQueue.size > 0) {
const workingCnt = this.works.filter((work) => ...).length;
if (workingCnt < this.maxWorker) {
const work = this.workQueue.next();
if (work) this.work(work);
} else {
await new Promise((resolve) => setTimeout(resolve, 300));
}
}
}
}
class UniqueQueue<T> {
private storage: Set<T>;
constructor(iterable?: Iterable<T> | null | undefined) {
this.storage = new Set<T>(iterable ? iterable : undefined);
}
get size(): number {
return this.storage.size;
}
public add(item: T) {
if (this.storage.has(item)) {
return;
}
this.storage.add(item);
}
public next(): T | undefined {
const entry = this.storage.entries().next();
if (!entry.done) {
const value = entry.value[0];
this.storage.delete(value);
return value;
} else {
return undefined;
}
}
}
Iterable 객체(배열)를 받아 storage 프로퍼티에 Set<T> 생성하고, push, pop 기능을 add(push), next(pop) 메서드로 구현하였다. 기능상 문제는 없었지만, 직접 구현한 UniqueQueue 보다 배열의 Iterator 객체를 활용한 코드가 별도의 class 구현 없이 깔끔하고, 직관적일 것이라 생각되었다.
Iterator를 이용한 구현
class Worker {
private readonly works: Work[];
private readonly workIterator: Iterator<Work>;
private readonly maxWorker = 60;
constructor(requests: WorkRequest[]) {
this.works = requests.map((r) => new Work(r));
this.workIterator = this.works[Symbol.iterator]();
}
public work(work: Work) {
...
}
public async run() {
let current = this.workIterator.next();
while (!current.done) {
const workingCnt = this.works.filter((work) => ...).length;
if (workingCnt < this.maxWorker) {
if (current.value) {
this.work(current.value);
current = this.workIterator.next();
}
} else {
await new Promise((resolve) => setTimeout(resolve, 300));
}
}
}
}
Iterable 객체(Array, String, Map, Set 등)인 배열은 iterator 객체를 반환하는 메서드인 Symbol.iterator 프로퍼티를 갖고 있다. Array[Symbol.iterator]() Symbol key를 이용하여 쉽게 Iterator 객체를 생성할 수 있다.
반응형
'Javascript' 카테고리의 다른 글
Turborepo 모노레포 적용하기 (1) | 2025.01.08 |
---|---|
<span>,<div>에 focus 적용 (0) | 2024.12.19 |
디바운싱(debouncing) / 쓰로틀링(throttling) (0) | 2024.11.14 |
Javascript 정규표현식으로 URL 찾아서 변환하기 (0) | 2023.11.23 |