-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathArrayStream.js
More file actions
129 lines (110 loc) · 2.5 KB
/
Copy pathArrayStream.js
File metadata and controls
129 lines (110 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* ArrayStream -- ReadableStream of arrays or hash variables
* @author SHIN Suzuki
*
*/
var Stream = require('stream').Stream;
nextTick = process.nextTick;
/**
* @constructor
*
* @param {Array} or {Object} arr
* @param {Object} op
* {boolean} tolerant if true, continue iteration even if errors occurred
*
* @event {data} function(value, key)
* Emitted when received an element.
*
* @event {end} function()
* Emitted when reached end
*
* @event {error} function(e)
* Emitted when an error occurred
**/
function ArrayStream(arr, op) {
op = op || {};
this.i = 0;
this.readable = true;
this.paused = !!op.pause;
this.arr = arr || [];
this.isArray = Array.isArray(arr);
this.keys = Object.keys(arr);
this.length = this.keys.length;
this._options = op;
if (!this.paused) nextTick(emit.bind(this));
}
ArrayStream.create = function(arr, op) {
return new this(arr, op);
};
ArrayStream.forEach = function(arr, op, fn) {
var args = Array.prototype.slice.call(arguments);
var arg = args.shift();
var fn = args.pop();
var stream = ArrayStream.create(arg, args.length? args[0]: null);
stream.on("data", function(value, key) {
fn(value, key);
});
return stream;
};
/**
* extends Stream
**/
require('util').inherits(ArrayStream, Stream);
/**
* @see ReadableStream
**/
ArrayStream.prototype.resume = function() {
this.paused = false;
emit.call(this);
};
/**
* @see ReadableStream
**/
ArrayStream.prototype.pause = function() {
this.paused = true;
};
/**
* @see ReadableStream
**/
ArrayStream.prototype.destroy = function() { // implementing ReadableStream
this.stream.destroy();
this.readable = false;
}
/**
* @see ReadableStream
**/
ArrayStream.prototype.destroySoon = function() { // implementing ReadableStream
// Not knowing what to do, this remains unimplemented...
this.destroy();
}
/**
* private function
**/
function emit() {
var self = this;
(function execute() {
try {
if(self.i >= self.length) {
self.emit('end');
}
else {
var k = self.keys[self.i];
self.emit('data', self.arr[k], k);
self.i++;
if (!self.paused) nextTick(execute);
}
} catch (e) {
self.emit('error', e);
if (self._options.tolerant) {
self.i++;
if (!self.paused) nextTick(execute);
}
else {
self.emit('end');
self.readable = false;
}
}
})();
}
ArrayStream.version = '0.0.3';
module.exports = ArrayStream;