You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
throttle with default options invokes the function more frequently than expected. It seems very unlikely that this is intended behavior, and it's inconsistent with underscore behavior.
Reproductions steps:
Call a throttled function twice
leadingEdge is invoked
Wait for the throttle period (wait)
trailingEdge is invoked
Call the throttled function again immediately afterwards
leadingEdge is invoked, even though trailingEdge was just invoked
The root cause is fairly obvious, and has nothing to do with setTimeout inconsistencies. shouldInvoke looks like:
functionshouldInvoke(time){vartimeSinceLastCall=time-lastCallTime,timeSinceLastInvoke=time-lastInvokeTime;// Either this is the first call, activity has stopped and we're at the// trailing edge, the system time has gone backwards and we're treating// it as the trailing edge, or we've hit the `maxWait` limit.return(lastCallTime===undefined||(timeSinceLastCall>=wait)||(timeSinceLastCall<0)||(maxing&&timeSinceLastInvoke>=maxWait));}
timeSinceLastCall is the time since debounced was last invoked. Therefore, in the above scenario, on step 5 shouldInvoke returns true, and leadingEdge is called.
Discovered in a unit test that looks something like:
import{expect}from'chai';importsinonfrom'sinon';importthrottlefrom'lodash.throttle';describe('lodash.throttle',()=>{letclock;letinvokeCount;letlastInvoked;constfunc=()=>{invokeCount++;lastInvoked=Date.now();}constwaitFor=ms=>newPromise(resolve=>{setTimeout(resolve,ms);clock.tick(ms);});beforeEach(()=>{clock=sinon.useFakeTimers();invokeCount=0;lastInvoked=undefined;});afterEach(()=>clock.restore());it('invokes func at most once every 10 seconds',()=>{constthrottlePeriod=10;constthrottled=throttle(func,throttlePeriod);expect(invokeCount).to.equal(0);throttled();throttled();expect(invokeCount).to.equal(1);returnwaitFor(throttlePeriod).then(()=>{expect(invokeCount).to.equal(2);throttled();expect(invokeCount,`throttled was called ${invokeCount} in ${Date.now()} ms. Current Time: ${Date.now()}, lastInvoked: ${lastInvoked}`).to.equal(2);});});});
throttle
with default options invokes the function more frequently than expected. It seems very unlikely that this is intended behavior, and it's inconsistent with underscore behavior.Reproductions steps:
leadingEdge
is invokedwait
)trailingEdge
is invokedleadingEdge
is invoked, even thoughtrailingEdge
was just invokedThe root cause is fairly obvious, and has nothing to do with setTimeout inconsistencies.
shouldInvoke
looks like:timeSinceLastCall
is the time sincedebounced
was last invoked. Therefore, in the above scenario, on step 5shouldInvoke
returnstrue
, andleadingEdge
is called.Discovered in a unit test that looks something like:
Also played with these to verify:
Lodash throttle fiddle: http://jsfiddle.net/sccqve9m/
Underscore throttle fiddle: http://jsfiddle.net/missinglink/19e2r2we/
The text was updated successfully, but these errors were encountered: