@@ -2,6 +2,7 @@ import * as fs from "fs";
2
2
import { asyncForEach as forEach } from "../async/for-each" ;
3
3
import { DirectoryReader } from "../directory-reader" ;
4
4
import { Options , Stats } from "../types-public" ;
5
+ import { Pending , pending } from "./pending" ;
5
6
6
7
const iteratorFacade = { fs, forEach } ;
7
8
@@ -25,27 +26,25 @@ export function readdirIterator<T>(dir: string, options?: Options): AsyncIterabl
25
26
let reader = new DirectoryReader ( dir , options , iteratorFacade ) ;
26
27
let stream = reader . stream ;
27
28
let pendingValues : T [ ] = [ ] ;
28
- let pendingNext : Promise < IteratorResult < T > > | undefined ;
29
- let resolvePendingNext : ( ( result : IteratorResult < T > ) => void ) | undefined ;
30
- let rejectPendingNext : ( ( error : Error ) => void ) | undefined ;
29
+ let pendingReads : Array < Pending < IteratorResult < T > > > = [ ] ;
31
30
let error : Error | undefined ;
32
31
let readable = false ;
33
32
let done = false ;
34
33
35
34
stream . on ( "error" , function streamError ( err : Error ) {
36
35
error = err ;
37
36
stream . pause ( ) ;
38
- fulfillPendingNextIfPossible ( ) ;
37
+ fulfillPendingReads ( ) ;
39
38
} ) ;
40
39
41
40
stream . on ( "end" , function streamEnd ( ) {
42
41
done = true ;
43
- fulfillPendingNextIfPossible ( ) ;
42
+ fulfillPendingReads ( ) ;
44
43
} ) ;
45
44
46
45
stream . on ( "readable" , function streamReadable ( ) {
47
46
readable = true ;
48
- fulfillPendingNextIfPossible ( ) ;
47
+ fulfillPendingReads ( ) ;
49
48
} ) ;
50
49
51
50
return {
@@ -55,47 +54,38 @@ export function readdirIterator<T>(dir: string, options?: Options): AsyncIterabl
55
54
56
55
// tslint:disable-next-line: promise-function-async
57
56
next ( ) {
58
- if ( ! pendingNext ) {
59
- pendingNext = new Promise ( ( resolve , reject ) => {
60
- resolvePendingNext = resolve ;
61
- rejectPendingNext = reject ;
62
- } ) ;
63
- }
57
+ let pendingRead = pending < IteratorResult < T > > ( ) ;
58
+ pendingReads . push ( pendingRead ) ;
64
59
65
60
// tslint:disable-next-line: no-floating-promises
66
- Promise . resolve ( ) . then ( fulfillPendingNextIfPossible ) ;
67
- return pendingNext ;
61
+ Promise . resolve ( ) . then ( fulfillPendingReads ) ;
62
+
63
+ return pendingRead . promise ;
68
64
}
69
65
} ;
70
66
71
- function fulfillPendingNextIfPossible ( ) {
72
- let fulfill , result ;
73
-
74
- if ( resolvePendingNext && rejectPendingNext ) {
75
- if ( error ) {
76
- fulfill = rejectPendingNext ;
77
- result = error ;
67
+ function fulfillPendingReads ( ) {
68
+ if ( error ) {
69
+ while ( pendingReads . length > 0 ) {
70
+ let pendingRead = pendingReads . shift ( ) ! ;
71
+ pendingRead . reject ( error ) ;
78
72
}
79
- else {
73
+ }
74
+ else if ( pendingReads . length > 0 ) {
75
+ while ( pendingReads . length > 0 ) {
76
+ let pendingRead = pendingReads . shift ( ) ! ;
80
77
let value = getNextValue ( ) ;
81
78
82
79
if ( value ) {
83
- fulfill = resolvePendingNext ;
84
- result = { value } ;
80
+ pendingRead . resolve ( { value } ) ;
85
81
}
86
82
else if ( done ) {
87
- fulfill = resolvePendingNext ;
88
- result = { done, value } ;
83
+ pendingRead . resolve ( { done, value } ) ;
84
+ }
85
+ else {
86
+ pendingReads . unshift ( pendingRead ) ;
87
+ break ;
89
88
}
90
- }
91
-
92
- if ( fulfill ) {
93
- // NOTE: It's important to clear these BEEFORE fulfilling the Promise;
94
- // otherwise a sporadic race condition can occur.
95
- pendingNext = resolvePendingNext = rejectPendingNext = undefined ;
96
-
97
- // @ts -ignore
98
- fulfill ( result ) ;
99
89
}
100
90
}
101
91
}
0 commit comments