Skip to content

Commit

Permalink
Improved progress throttling logic;
Browse files Browse the repository at this point in the history
Added ability to set innerWeight to 0 for manual progress calculation;
  • Loading branch information
DigitalBrainJS committed Jan 29, 2022
1 parent 1d741fe commit 185dd8a
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 33 deletions.
51 changes: 27 additions & 24 deletions lib/c-promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const {
getFnType,
lazyBindMethods,
isContextDefined,
getTag
getTag,
throttle
} = require('./utils');
const {classDecorator, propertyDecorator, bindDecorators}= require('./decorators');
const {versionNumber, _versionNumber, _version, version, warnVersionInteraction}= require('./env');
Expand Down Expand Up @@ -164,7 +165,7 @@ const CPromise= class CPromise extends Promise {
progress: 0,
computedProgress: -1,
totalWeight: -1,
innerWeight: 0,
innerWeight: 1,
throttle: 0,
throttleTimer: 0,
isCaptured: false,
Expand Down Expand Up @@ -347,8 +348,8 @@ const CPromise= class CPromise extends Promise {
throw Error('inner weight must be a number')
}

if (weight <= 0) {
throw Error('inner weight must be greater than 0')
if (weight < 0) {
throw Error('inner weight cannot be less than 0');
}

this[_shadow].innerWeight = weight;
Expand All @@ -375,6 +376,8 @@ const CPromise= class CPromise extends Promise {

if (arguments.length) {

if (!shadow.isPending) return this;

if (typeof value === 'function') {
this.on('progress', value);
return this;
Expand All @@ -399,17 +402,11 @@ const CPromise= class CPromise extends Promise {
if (shadow.progress !== value) {
shadow.progress = value;

if (value !== 1 && shadow.throttle) {
if (!shadow.throttleTimer) {
shadow.throttleTimer = setTimeout(() => {
shadow.throttleTimer = 0;
this.propagate(TYPE_PROGRESS, data, scope);
}, shadow.throttle);
}
return this;
if(value !== 1 && shadow.throttler){
shadow.throttler([data, scope]);
} else {
this.propagate(TYPE_PROGRESS, data, scope);
}

this.propagate(TYPE_PROGRESS, data, scope);
}

return this;
Expand Down Expand Up @@ -466,24 +463,27 @@ const CPromise= class CPromise extends Promise {
*/

captureProgress(options) {
const shadow = this[_shadow];

if (options) {
validateOptions(options, {
throttle: numberFinitePositive,
innerWeight: numberFinitePositive
})
}

const {throttle, innerWeight} = options;
const {throttle: ms = 200, innerWeight} = options || {};

if (throttle !== undefined) {
this[_shadow].throttle = throttle;
}
shadow.throttler && shadow.throttler.cancel();

if (innerWeight !== undefined) {
this.innerWeight(innerWeight);
}
shadow.throttler = ms ? throttle((data, scope) => {
this.propagate(TYPE_PROGRESS, data, scope);
}, ms) : null;

if (innerWeight !== undefined) {
this.innerWeight(innerWeight);
}

const shadow = this[_shadow];
const scopes = this.scopes(true);
let i = scopes.length;
let sum = 0;
Expand Down Expand Up @@ -1295,7 +1295,8 @@ const CPromise= class CPromise extends Promise {
});

const handleProgress = (value, _scope, data) => {
let total = scope.innerWeight() || 1;
let total = scope.innerWeight();
if (!total) return;
let sum = progressAcc;
const {length} = pending;
for (let i = 0; i < length; i++) {
Expand Down Expand Up @@ -1880,7 +1881,9 @@ const CPromise= class CPromise extends Promise {
let promise;

const setProgress = (value, _scope, data) => {
progress = (value * weight + sum) / (scope.innerWeight() || 1);
const innerWeight = scope.innerWeight();
if (!innerWeight) return;
progress = (value * weight + sum) / innerWeight;
scope.progress(progress, _scope, data);
}

Expand Down
43 changes: 41 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ const isPropertyDescriptor = ((allowed)=>{
configurable: true
});


const lazyBindMethods = (obj, props) => {
props.forEach(prop => {
const symbol = Symbol(`${prop}Bound`);
Expand Down Expand Up @@ -102,6 +101,45 @@ const globalObject= (()=>{

const isContextDefined = (context) => context != null && context !== globalObject;

const throttle = (fn, ms) => {
let timer = null;
let lastArgs = null;
let last = null;

const cancel = ()=>{
if (!timer) return;
clearTimeout(timer);
timer = null;
lastArgs = null;
}

const wrapper = function (args, force) {
const now = Date.now();
const left = ms - (now - last);

if (force || left <= 0) {
fn.apply(this, args);
last = now;
cancel();
return true;
}

lastArgs = args;

timer = setTimeout(()=>{
fn.apply(this, args);
last = now;
lastArgs = null;
}, left);

return false;
};

wrapper.cancel = cancel;

return wrapper;
}

module.exports={
isPropertyDescriptor,
isThenable,
Expand All @@ -116,5 +154,6 @@ module.exports={
globalObject,
isContextDefined,
hasOwnProperty,
getTag
getTag,
throttle
};
15 changes: 8 additions & 7 deletions test/tests/CPromise.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ module.exports = {
assert.fail('promise has not been canceled');
}, (err) => {
if (err instanceof CPromise.CanceledError) {
if (Date.now() - timestamp < timeout) {
if (Date.now() - timestamp + 5 < timeout) {
assert.fail('early cancellation detected')
}
return;
Expand Down Expand Up @@ -241,7 +241,7 @@ module.exports = {
})
.then(() => {
assertProgress(0.8)
});//.captureProgress();
});

const assertProgress = (expected) => {
assert.equal(chain.progress(), expected);
Expand Down Expand Up @@ -379,7 +379,7 @@ module.exports = {
}
},

'CPromise#setProgress()': {
'CPromise#progress()': {
'should set the value of the promise progress': function (done) {
const p = new CPromise(function (resolve, reject) {
let progress = 0;
Expand All @@ -392,7 +392,7 @@ module.exports = {
resolve('done');
}

}, 10);
}, 200);
});

const expect = [0.2, 0.4, 0.6, 0.8, 1];
Expand Down Expand Up @@ -530,20 +530,21 @@ module.exports = {

'progress capturing': {
'should support progress capturing': async function () {
this.timeout(5000);
const expected = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1];
let index = 0;

const fn= CPromise.promisify(function*(){
this.innerWeight(2);
yield CPromise.delay(100);
yield CPromise.delay(100);
yield CPromise.delay(250);
yield CPromise.delay(250);
})

return CPromise.resolve(function* () {
this.innerWeight(10);
let i = 9;
while (--i >= 0) {
yield CPromise.delay(100);
yield CPromise.delay(250);
}
yield fn();
}).progress(value => {
Expand Down

0 comments on commit 185dd8a

Please sign in to comment.