You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
49 lines
1.2 KiB
49 lines
1.2 KiB
module.exports = async function* iterateStream(stream) {
|
|
const contents = [];
|
|
stream.on('data', data => contents.push(data));
|
|
|
|
let resolveStreamEndedPromise;
|
|
const streamEndedPromise = new Promise(resolve => (resolveStreamEndedPromise = resolve));
|
|
|
|
let ended = false;
|
|
stream.on('end', () => {
|
|
ended = true;
|
|
resolveStreamEndedPromise();
|
|
});
|
|
|
|
let error = false;
|
|
stream.on('error', err => {
|
|
error = err;
|
|
resolveStreamEndedPromise();
|
|
});
|
|
|
|
while (!ended || contents.length > 0) {
|
|
if (contents.length === 0) {
|
|
stream.resume();
|
|
// eslint-disable-next-line no-await-in-loop
|
|
await Promise.race([once(stream, 'data'), streamEndedPromise]);
|
|
} else {
|
|
stream.pause();
|
|
const data = contents.shift();
|
|
yield data;
|
|
}
|
|
if (error) throw error;
|
|
}
|
|
resolveStreamEndedPromise();
|
|
};
|
|
|
|
function once(eventEmitter, type) {
|
|
// TODO: Use require('events').once when node v10 is dropped
|
|
return new Promise(resolve => {
|
|
let fired = false;
|
|
const handler = () => {
|
|
if (!fired) {
|
|
fired = true;
|
|
eventEmitter.removeListener(type, handler);
|
|
resolve();
|
|
}
|
|
};
|
|
eventEmitter.addListener(type, handler);
|
|
});
|
|
}
|