Simulate smooth progression easily and combine real progression and fake progression.
npm install fake-progress
var FakeProgress = require("fake-progress");
// Create the fake progress with a timeConstant of 10 seconds
// it means that :
// after 10 seconds, progress will be 0.6321 ( = 1-Math.exp(-1) )
// after 20 seconds, progress will be 0.8646 ( = 1-Math.exp(-2) )
// and so on
var p = new FakeProgress({
timeConstant : 10000,
autoStart : true
});
var exampleAsyncFunction = function(callback){
setTimeout(function(){
callback()
},30000)
};
var onEachSecond = function(){
console.log("Progress is "+(p.progress*100).toFixed(1)+" %");
};
var interval = setInterval(onEachSecond, 1000);
var onEnd = function(){
p.end();
clearInterval(interval);
console.log("Ended. Progress is "+(p.progress*100).toFixed(1)+" %")
};
exampleAsyncFunction(onEnd);
will print
Progress is 8.6 %
Progress is 17.3 %
Progress is 25.2 %
Progress is 32.3 %
...
The chart of progression over time.
Until the end is triggered, the progression is following the exponential curve, once "end" is triggered, progression goes to 100%.
In this example we will mix 3 functions, A and C are classical async functions, B is an async function with a 'real' progression callback.
a and c are 2 basic async functions without progress.
const a = function (cb) {
setTimeout(() => {
cb();
}, 1000);
};
const c = function (cb) {
setTimeout(() => {
cb();
}, 3000);
};
b will be an instance of an event emmiter that has a progress event
const B = function () {
EventEmitter.call(this);
let count = 0;
const self = this;
const totalCount = 30;
self.emit('start', count / totalCount);
self._intervalId = setInterval(() => {
count++;
if (count >= totalCount) {
self.emit('end', count / totalCount);
clearInterval(self._intervalId);
} else {
self.emit('progress', count / totalCount);
}
}, 100);
};
util.inherits(B, EventEmitter);
const p = new FakeProgress({});
const onEachDeciSecond = function () {
console.log('Progress is ' + (p.progress * 100).toFixed(1) + ' %');
};
onEachDeciSecond();
const interval = setInterval(onEachDeciSecond, 100);
A has no progress so we fake his progress. A succeed in 1000 ms, so we can consider 500 ms is a good timeConstant.
const aProgress = p.createSubProgress({
timeConstant: 500,
end: 0.3,
autoStart: true
});
Each time on the async chain, subProgress.stop() then call createSubProgress() to create a new subProgress.
a(err => {
if (err) {
throw (err);
}
aProgress.stop();
const bProgress = p.createSubProgress({
end: 0.8
});
const b = new B();
b.on('progress', progress => {
bProgress.setProgress(progress);
});
b.on('end', () => {
bProgress.stop();
const cProgress = p.createSubProgress({
timeConstant: 1000,
autoStart: true
});
c(() => {
cProgress.end();
onEachDeciSecond();
clearInterval(interval);
});
});
});
After each call, stop previous sub, and create a new subProgress for next request.
a(function(){
aProgress.stop();
var bProgress = p.createSubProgress({
end : 0.8
});
var b = new B();
b.on('progress', function(progress){
bProgress.setProgress(progress);
});
b.on('end', function(){
bProgress.stop();
var cProgress = p.createSubProgress({
timeConstant : 1000,
autoStart : true
});
c(function(){
cProgress.end()
onEachDeciSecond()
clearInterval(interval);
})
});
});
see source
See inside the code, documentated using JSDoc