https://github.com/nichoth/node-style-adventure
Demo of functional and object oriented patterns
https://github.com/nichoth/node-style-adventure
Last synced: 11 days ago
JSON representation
Demo of functional and object oriented patterns
- Host: GitHub
- URL: https://github.com/nichoth/node-style-adventure
- Owner: nichoth
- Created: 2017-12-30T19:49:44.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2018-02-10T20:16:45.000Z (over 8 years ago)
- Last Synced: 2025-03-10T06:37:25.613Z (over 1 year ago)
- Language: JavaScript
- Homepage:
- Size: 14.6 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
Take multiple s3 uploads, and return progress events for the total progress for all the uploads combined. Each s3 upload object emits events like `{ loaded: 1, total 10 }`, but `total` may be undefined because it has not yet been calculated.
## Event emitter
```js
var inherits = require('util').inherits
var EE = require('events').EventEmitter
// take multiple s3 uploads and return a single event emitter with
// total progress
function UploadProgress (uploads) {
if (!(this instanceof UploadProgress)) {
return new UploadProgress(uploads);
}
this.uploads = uploads;
var bus = this;
var totals = uploads.map(() => null);
var sum;
var progresses = uploads.map(() => 0);
var isReady = false;
this._stateListeners = [];
this._progressListener = emitProgress;
var self = this;
uploads.forEach(function (upload, i) {
self._stateListeners.push(getState);
upload.on('httpUploadProgress', getState);
function getState (data) {
progresses[i] = data.loaded;
if (isReady) return; // we have all the totals already
if (data.total) totals[i] = data.total;
if (totals.every(Boolean)) {
isReady = true;
sum = totals.reduce((_sum, n) => _sum + n);
}
}
});
// emit the overall progress
var prev;
uploads.forEach(function (upload, i) {
upload.on('httpUploadProgress', emitProgress);
});
function emitProgress (data) {
if (!isReady) return;
var prog = progresses.reduce((acc, n) => acc + n);
var percent = Math.floor(prog / sum * 100);
if (prev === percent) return; // filter duplicate values
prev = percent;
bus.emit('progress', percent);
}
EE.call(this);
}
inherits(UploadProgress, EE);
UploadProgress.prototype.close = function () {
var self = this;
this.uploads.forEach(function (upload, i) {
upload.removeListener('httpUploadProgress', self._stateListeners[i]);
upload.removeListener('httpUploadProgress', self._progressListener);
});
this.removeAllListeners();
};
module.exports = UploadProgress;
```
## pull stream
Why is this version smaller than the OO example? Where is the the equivalent state in here?
```js
var S = require('pull-stream')
var _ = require('pull-stream-util')
function Progress (uploads) {
var uploadStreams = uploads.map(_.fromEvent('httpUploadProgress'))
var progress$ = S(
_.combineLatest(uploadStreams),
_.scan(function (state, evs) {
var sum = state.sum || (evs.every(ev => ev.total) ?
evs.reduce((_sum, ev) => _sum + ev.total, 0) :
null)
if (!sum) return state
var prog = evs.reduce((sum, ev) => sum + ev.loaded, 0)
return { sum, percent: Math.floor(prog / sum * 100) }
}, { sum: null, percent: null }),
S.filter(state => state.sum),
S.map(state => state.percent)
)
progress$.close = function () {
uploadStreams.forEach(up => up.end())
}
return progress$
}
module.exports = Progress
```
## benchmark
Which will be faster? What is a good way to test this? [/test/bench/index.js](/test/bench/index.js)
```
benchStream*10000: 463.748ms
benchEmitter*10000: 255.184ms
benchStream*10000: 499.722ms
benchEmitter*10000: 276.881ms
```