1
+ import { TaskQueuePC } from './11-asyncawait-web-spider-v4/TaskQueuePC.js' ;
2
+
3
+ /**
4
+ * ### 프라미스와 동시성 제한을 지원하는 Array.map() 의 비동기 병렬 버전을 구현하기
5
+ * - 소개된 패턴은 사용해도 되지만, TaskQueue, TaskQueuePC 를 직접적으로 보완하지 않아야 함.
6
+ *
7
+ * @param {Iterable<any> } iterable 이터러블
8
+ * @param {(item) => Promise<any> } callback 이터러블의 각 아이템을 입력으로 받고 프라미스와 간단한 값을 반환하는 콜백
9
+ * @param {number } concurrency 이터러블에서 얼마나 많은 아이템이 벙렬로 처리될 수 있는지 정의하는 동시성
10
+ */
11
+ async function mapAsync ( iterable , callback , concurrency ) {
12
+ const result = [ ] ;
13
+ const taskQueue = new TaskQueuePC ( concurrency ) ;
14
+
15
+ const arrayFromIter = [ ...iterable ] ;
16
+
17
+ await arrayFromIter . reduce ( async ( acc , item ) => {
18
+ try {
19
+ const value = await taskQueue . runTask ( ( ) => callback ( item ) )
20
+ await acc ;
21
+ return result . push ( value ) ;
22
+ } catch ( err ) {
23
+ throw err ;
24
+ }
25
+ } , Promise . resolve ( ) ) ;
26
+
27
+ return result ;
28
+ }
29
+
30
+
31
+
32
+ // ---------- TEST ----------------------------------------
33
+
34
+ const testIter = function * ( ) {
35
+ for ( let i = 1 ; i <= 5 ; i ++ ) {
36
+ yield i ;
37
+ }
38
+ } ;
39
+ const callbackAsync = async ele => {
40
+ return new Promise ( resolve => {
41
+ setTimeout ( ( ) => {
42
+ resolve ( ele * 2 )
43
+ } , ele % 2 === 0 ? 100 : 200 )
44
+ } )
45
+ } ;
46
+
47
+ // 항상 [ 2, 4, 6, 8, 10 ] 로, callback 실행 순서와 관계없이 요소들의 순서는 보존되어야함.
48
+ // concurrency 가 2 일떄 500ms, 3 일때 400ms, 4 일떄 300ms, 5일때 200ms 가 걸림.
49
+
50
+ console . time ( 'mapAsync-2_expect: 500ms' ) ;
51
+ console . log ( await mapAsync ( testIter ( ) , callbackAsync , 2 ) ) ;
52
+ console . timeEnd ( 'mapAsync-2_expect: 500ms' ) ;
53
+
54
+ console . time ( 'mapAsync-3_expect: 400ms' ) ;
55
+ console . log ( await mapAsync ( testIter ( ) , callbackAsync , 3 ) ) ;
56
+ console . timeEnd ( 'mapAsync-3_expect: 400ms' ) ;
57
+
58
+ console . time ( 'mapAsync-4_expect: 300ms' ) ;
59
+ console . log ( await mapAsync ( testIter ( ) , callbackAsync , 4 ) ) ;
60
+ console . timeEnd ( 'mapAsync-4_expect: 300ms' ) ;
61
+
62
+ console . time ( 'mapAsync-5_expect: 200ms' ) ;
63
+ console . log ( await mapAsync ( testIter ( ) , callbackAsync , 5 ) ) ;
64
+ console . timeEnd ( 'mapAsync-5_expect: 200ms' ) ;
0 commit comments