@@ -38,6 +38,69 @@ const map = (
38
38
}
39
39
} ;
40
40
41
+ const DEFAULT_OPTIONS = { min : 5 , percent : 0.7 } ;
42
+
43
+ // Non-blocking synchronous map
44
+ // items - <Array>, incoming dataset
45
+ // fn - <Function>
46
+ // item - <any>
47
+ // index - <number>
48
+ // options - <Object>, map params { min, percent }
49
+ // min - <number>, min number of items in one next call
50
+ // percent - <number>, ratio of map time to all time
51
+ // done - <Function>, call on done
52
+ // err - <Error> | <null>
53
+ // result - <Array>
54
+ const asyncMap = ( items , fn , options = { } , done ) => {
55
+ if ( typeof options === 'function' ) {
56
+ done = options ;
57
+ options = DEFAULT_OPTIONS ;
58
+ }
59
+
60
+ if ( ! items . length ) {
61
+ if ( done ) done ( null , [ ] ) ;
62
+ return ;
63
+ }
64
+
65
+ const min = options . min || DEFAULT_OPTIONS . min ;
66
+ const percent = options . percent || DEFAULT_OPTIONS . percent ;
67
+
68
+ let begin ;
69
+ let sum = 0 ;
70
+ let count = 0 ;
71
+
72
+ const result = done ? new Array ( items . length ) : null ;
73
+ const ratio = percent / ( 1 - percent ) ;
74
+
75
+ const countNumber = ( ) => {
76
+ const loopTime = Date . now ( ) - begin ;
77
+ const itemTime = sum / count ;
78
+ const necessaryNumber = ratio * loopTime / itemTime ;
79
+ return Math . max ( necessaryNumber , min ) ;
80
+ } ;
81
+
82
+ const next = ( ) => {
83
+ const itemsNumber = count ? countNumber ( ) : min ;
84
+ const iterMax = Math . min ( items . length , itemsNumber + count ) ;
85
+
86
+ begin = Date . now ( ) ;
87
+ for ( ; count < iterMax ; count ++ ) {
88
+ const itemResult = fn ( items [ count ] , count ) ;
89
+ if ( done ) result [ count ] = itemResult ;
90
+ }
91
+ sum += Date . now ( ) - begin ;
92
+
93
+ if ( count < items . length ) {
94
+ begin = Date . now ( ) ;
95
+ setTimeout ( next , 0 ) ;
96
+ } else if ( done ) {
97
+ done ( null , result ) ;
98
+ }
99
+ } ;
100
+
101
+ next ( ) ;
102
+ } ;
103
+
41
104
const filter = (
42
105
// Asynchrous filter (iterate parallel)
43
106
items , // array, incoming
@@ -303,4 +366,5 @@ module.exports = {
303
366
find,
304
367
every,
305
368
some,
369
+ asyncMap,
306
370
} ;
0 commit comments