2
2
3
3
const common = require ( '@metarhia/common' ) ;
4
4
5
+ const copy = name => {
6
+ switch ( name ) {
7
+ case 'Set' :
8
+ return new Set ( ) ;
9
+ case 'Map' :
10
+ return new Map ( ) ;
11
+ case 'Array' :
12
+ return [ ] ;
13
+ case 'String' :
14
+ return '' ;
15
+ }
16
+ return null ;
17
+ } ;
18
+
5
19
// Asynchronous map (iterate parallel)
6
20
// items - <Array>, incoming
7
21
// fn - <Function>, to be executed for each value in the array
@@ -12,31 +26,47 @@ const common = require('@metarhia/common');
12
26
// done - <Function>, on done, optional
13
27
// err - <Error> | <null>
14
28
// result - <Array>
15
- const map = ( items , fn , done ) => {
29
+ const map = (
30
+ // Asynchronous map (iterate parallel)
31
+ items , // array, incoming
32
+ fn , // function, (current, callback) => callback(err, value)
33
+ // to be executed for each value in the array
34
+ // current - current element being processed in the array
35
+ // callback - function(err, value)
36
+ done // function (optional), on done callback function(err, result)
37
+ ) => {
16
38
done = done || common . emptyness ;
17
- const len = items . length ;
18
- if ( ! len ) {
19
- done ( null , [ ] ) ;
39
+ const len = items . length || items . size ;
40
+ const name = items . constructor . name ;
41
+ let result = copy ( name ) ;
42
+ if ( ! len || ! result ) {
43
+ done ( null , result ) ;
20
44
return ;
21
45
}
22
46
let errored = false ;
23
47
let count = 0 ;
24
- const result = new Array ( len ) ;
48
+ const data = items [ Symbol . iterator ] ( ) ;
25
49
26
- const next = ( index , err , value ) => {
50
+ const next = ( err , value ) => {
27
51
if ( errored ) return ;
28
52
if ( err ) {
29
53
errored = true ;
30
54
done ( err ) ;
31
55
return ;
32
56
}
33
- result [ index ] = value ;
57
+ if ( name === 'Array' ) result . push ( value ) ;
58
+ else if ( name === 'Set' ) result . add ( value ) ;
59
+ else if ( name === 'Map' ) result . set ( value [ 0 ] , value [ 1 ] ) ;
60
+ else result += value ;
34
61
count ++ ;
35
62
if ( count === len ) done ( null , result ) ;
36
63
} ;
37
64
38
- for ( let i = 0 ; i < len ; i ++ ) {
39
- fn ( items [ i ] , next . bind ( null , i ) ) ;
65
+ let i = 0 ;
66
+ while ( i < len ) {
67
+ const item = data . next ( ) ;
68
+ fn ( item . value , next ) ;
69
+ i ++ ;
40
70
}
41
71
} ;
42
72
@@ -59,8 +89,13 @@ const asyncMap = (items, fn, options = {}, done) => {
59
89
options = DEFAULT_OPTIONS ;
60
90
}
61
91
62
- if ( ! items . length ) {
63
- if ( done ) done ( null , [ ] ) ;
92
+ const len = items . length || items . size ;
93
+ const name = items . constructor . name ;
94
+ let result = done ? copy ( name ) : null ;
95
+ const data = items [ Symbol . iterator ] ( ) ;
96
+
97
+ if ( ! len || ! result ) {
98
+ if ( done ) done ( null , result ) ;
64
99
return ;
65
100
}
66
101
@@ -71,7 +106,6 @@ const asyncMap = (items, fn, options = {}, done) => {
71
106
let sum = 0 ;
72
107
let count = 0 ;
73
108
74
- const result = done ? new Array ( items . length ) : null ;
75
109
const ratio = percent / ( 1 - percent ) ;
76
110
77
111
const countNumber = ( ) => {
@@ -83,16 +117,21 @@ const asyncMap = (items, fn, options = {}, done) => {
83
117
84
118
const next = ( ) => {
85
119
const itemsNumber = count ? countNumber ( ) : min ;
86
- const iterMax = Math . min ( items . length , itemsNumber + count ) ;
120
+ const iterMax = Math . min ( len , itemsNumber + count ) ;
87
121
88
122
begin = Date . now ( ) ;
89
123
for ( ; count < iterMax ; count ++ ) {
90
- const itemResult = fn ( items [ count ] , count ) ;
91
- if ( done ) result [ count ] = itemResult ;
124
+ const itemResult = fn ( data . next ( ) . value , count ) ;
125
+ if ( done ) {
126
+ if ( name === 'Array' ) result . push ( itemResult ) ;
127
+ else if ( name === 'Set' ) result . add ( itemResult ) ;
128
+ else if ( name === 'Map' ) result . set ( itemResult [ 0 ] , itemResult [ 1 ] ) ;
129
+ else result += itemResult ;
130
+ }
92
131
}
93
132
sum += Date . now ( ) - begin ;
94
133
95
- if ( count < items . length ) {
134
+ if ( count < len ) {
96
135
begin = Date . now ( ) ;
97
136
setTimeout ( next , 0 ) ;
98
137
} else if ( done ) {
@@ -115,39 +154,36 @@ const asyncMap = (items, fn, options = {}, done) => {
115
154
// result - <Array>
116
155
const filter = ( items , fn , done ) => {
117
156
done = done || common . emptyness ;
118
- const len = items . length ;
157
+ const len = items . length || items . size ;
158
+ const data = items [ Symbol . iterator ] ( ) ;
159
+ const name = items . constructor . name ;
160
+ let result = copy ( name ) ;
119
161
120
- if ( ! len ) {
121
- done ( null , [ ] ) ;
162
+ if ( ! len || ! result ) {
163
+ done ( null , result ) ;
122
164
return ;
123
165
}
124
166
125
167
let count = 0 ;
126
- let suitable = 0 ;
127
- const data = new Array ( len ) ;
128
- const rejected = Symbol ( 'rejected' ) ;
129
-
130
- const next = ( index , err , accepted ) => {
131
- if ( ! accepted || err ) {
132
- data [ index ] = rejected ;
133
- } else {
134
- data [ index ] = items [ index ] ;
135
- suitable ++ ;
168
+
169
+ const next = ( value , err , accepted ) => {
170
+ if ( accepted && ! err ) {
171
+ if ( name === 'Array' ) result . push ( value ) ;
172
+ else if ( name === 'Set' ) result . add ( value ) ;
173
+ else if ( name === 'Map' ) result . set ( value [ 0 ] , value [ 1 ] ) ;
174
+ else result += value ;
136
175
}
137
176
count ++ ;
138
177
if ( count === len ) {
139
- const result = new Array ( suitable ) ;
140
- let pos = 0 ;
141
- for ( let i = 0 ; i < len ; i ++ ) {
142
- const val = data [ i ] ;
143
- if ( val !== rejected ) result [ pos ++ ] = val ;
144
- }
145
178
done ( null , result ) ;
146
179
}
147
180
} ;
148
181
149
- for ( let i = 0 ; i < len ; i ++ ) {
150
- fn ( items [ i ] , next . bind ( null , i ) ) ;
182
+ let i = 0 ;
183
+ while ( i < len ) {
184
+ const item = data . next ( ) ;
185
+ fn ( item . value , next . bind ( null , item . value ) ) ;
186
+ i ++ ;
151
187
}
152
188
} ;
153
189
@@ -173,7 +209,8 @@ const REDUCE_EMPTY_ARR =
173
209
// argument in first iteration
174
210
const reduce = ( items , fn , done , initial ) => {
175
211
done = done || common . emptyness ;
176
- const len = items . length ;
212
+ const len = items . length || items . size || 0 ;
213
+ items = [ ...items ] ;
177
214
const hasInitial = typeof initial !== 'undefined' ;
178
215
179
216
if ( len === 0 && ! hasInitial ) {
@@ -231,7 +268,8 @@ const REDUCE_RIGHT_EMPTY_ARR =
231
268
// argument in first iteration
232
269
const reduceRight = ( items , fn , done , initial ) => {
233
270
done = done || common . emptyness ;
234
- const len = items . length ;
271
+ const len = items . length || items . size || 0 ;
272
+ items = [ ...items ] ;
235
273
const hasInitial = typeof initial !== 'undefined' ;
236
274
237
275
if ( len === 0 && ! hasInitial ) {
@@ -276,10 +314,17 @@ const reduceRight = (items, fn, done, initial) => {
276
314
// done - <Function>, on done, optional
277
315
// err - <Error> | <null>
278
316
// items - <Array>
279
- const each = ( items , fn , done ) => {
317
+ const each = (
318
+ // Asynchronous each (iterate in parallel)
319
+ items , // array, incoming
320
+ fn , // function, (value, callback) => callback(err)
321
+ // value - item from items array
322
+ // callback - callback function(err)
323
+ done // function (optional), on done callback function(err, items)
324
+ ) => {
280
325
done = done || common . emptyness ;
281
- const len = items . length ;
282
- if ( len === 0 ) {
326
+ const len = items . length || items . size ;
327
+ if ( ! len ) {
283
328
done ( null , items ) ;
284
329
return ;
285
330
}
@@ -297,9 +342,7 @@ const each = (items, fn, done) => {
297
342
if ( count === len ) done ( null ) ;
298
343
} ;
299
344
300
- for ( let i = 0 ; i < len ; i ++ ) {
301
- fn ( items [ i ] , next ) ;
302
- }
345
+ for ( const item of items ) fn ( item , next ) ;
303
346
} ;
304
347
305
348
// Asynchronous series
@@ -311,9 +354,17 @@ const each = (items, fn, done) => {
311
354
// done - <Function>, on done, optional
312
355
// err - <Error> | <null>
313
356
// items - <Array>
314
- const series = ( items , fn , done ) => {
357
+ const series = (
358
+ // Asynchronous series
359
+ items , // array, incoming
360
+ fn , // function, (value, callback) => callback(err)
361
+ // value - item from items array
362
+ // callback - callback (err)
363
+ done // function (optional), on done callback (err, items)
364
+ ) => {
315
365
done = done || common . emptyness ;
316
- const len = items . length ;
366
+ const len = items . length || items . size ;
367
+ const data = items [ Symbol . iterator ] ( ) ;
317
368
let i = - 1 ;
318
369
319
370
const next = ( ) => {
@@ -322,7 +373,7 @@ const series = (items, fn, done) => {
322
373
done ( null , items ) ;
323
374
return ;
324
375
}
325
- fn ( items [ i ] , err => {
376
+ fn ( data . next ( ) . value , err => {
326
377
if ( err ) {
327
378
done ( err ) ;
328
379
return ;
@@ -345,15 +396,16 @@ const series = (items, fn, done) => {
345
396
// result - <any>
346
397
const find = ( items , fn , done ) => {
347
398
done = done || common . emptyness ;
348
- const len = items . length ;
349
- if ( len === 0 ) {
399
+ const len = items . length || items . size ;
400
+ const data = items [ Symbol . iterator ] ( ) ;
401
+ if ( ! len ) {
350
402
done ( ) ;
351
403
return ;
352
404
}
353
405
let finished = false ;
354
406
const last = len - 1 ;
355
407
356
- const next = ( index , err , accepted ) => {
408
+ const next = ( index , item , err , accepted ) => {
357
409
if ( finished ) return ;
358
410
if ( err ) {
359
411
finished = true ;
@@ -362,14 +414,15 @@ const find = (items, fn, done) => {
362
414
}
363
415
if ( accepted ) {
364
416
finished = true ;
365
- done ( null , items [ index ] ) ;
417
+ done ( null , item ) ;
366
418
return ;
367
419
}
368
420
if ( index === last ) done ( null ) ;
369
421
} ;
370
422
371
423
for ( let i = 0 ; i < len ; i ++ ) {
372
- fn ( items [ i ] , next . bind ( null , i ) ) ;
424
+ const item = data . next ( ) . value ;
425
+ fn ( item , next . bind ( null , i , item ) ) ;
373
426
}
374
427
} ;
375
428
@@ -383,14 +436,21 @@ const find = (items, fn, done) => {
383
436
// done - <Function>, on done, optional
384
437
// err - <Error> | <null>
385
438
// result - <boolean>
386
- const every = ( items , fn , done ) => {
439
+ const every = (
440
+ // Asynchronous every
441
+ items , // array, incoming
442
+ fn , // function, (value, callback) => callback(err, fits)
443
+ // value - item from items array
444
+ // callback - callback function(err, fits)
445
+ done // function, optional on done callback function(err, result)
446
+ ) => {
387
447
done = done || common . emptyness ;
388
- if ( items . length === 0 ) {
448
+ const len = items . length || items . size ;
449
+ if ( ! len ) {
389
450
done ( null , true ) ;
390
451
return ;
391
452
}
392
453
let proceedItemsCount = 0 ;
393
- const len = items . length ;
394
454
395
455
const finish = ( err , accepted ) => {
396
456
if ( ! done ) return ;
@@ -402,7 +462,6 @@ const every = (items, fn, done) => {
402
462
proceedItemsCount ++ ;
403
463
if ( proceedItemsCount === len ) done ( null , true ) ;
404
464
} ;
405
-
406
465
for ( const item of items ) fn ( item , finish ) ;
407
466
} ;
408
467
@@ -418,15 +477,16 @@ const every = (items, fn, done) => {
418
477
// result - <boolean>
419
478
const some = ( items , fn , done ) => {
420
479
done = done || common . emptyness ;
421
- const len = items . length ;
480
+ const len = items . length || items . size ;
481
+ const data = items [ Symbol . iterator ] ( ) ;
422
482
let i = 0 ;
423
483
424
484
const next = ( ) => {
425
485
if ( i === len ) {
426
486
done ( null , false ) ;
427
487
return ;
428
488
}
429
- fn ( items [ i ] , ( err , accepted ) => {
489
+ fn ( data . next ( ) . value , ( err , accepted ) => {
430
490
if ( err ) {
431
491
done ( err ) ;
432
492
return ;
0 commit comments