From e040afd33bd09fc83597422bf13117c49f542ecc Mon Sep 17 00:00:00 2001 From: Alex Liu Date: Fri, 20 Jan 2017 16:30:54 -0800 Subject: [PATCH] accept optional callback on stopping the interval --- lib/index.js | 40 +++++++++++++++++++++++++-- test/index.js | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index 56f1f1b..2a96170 100644 --- a/lib/index.js +++ b/lib/index.js @@ -77,6 +77,14 @@ function Reissue(opts) { opts.args.concat(boundDone) : [boundDone]; + /** + * stop callback. a callback to invoke when the final iteration of a + * task is complete. + * @type {Function} + */ + self._stopCallback = null; + + //-------------------------------------------------------------------------- // internal properties //-------------------------------------------------------------------------- @@ -117,6 +125,10 @@ Reissue.prototype._execute = function _execute() { if (self._active === true) { self._func.apply(self._funcContext, self._funcArgs); } + // if we're not active, call the callback and we're done. + else if (self._stopCallback) { + self._stopCallback(); + } }; @@ -141,7 +153,11 @@ Reissue.prototype._done = function _done(err) { } // if user called stop(), we're done! don't queue up another invocation. + // call the user callback and return. if (self._active === false) { + if (typeof self._stopCallback === 'function') { + self._stopCallback(); + } return; } @@ -199,11 +215,31 @@ Reissue.prototype.start = function start(delay) { * manually stop the exeuction queue. * @public * @method stop + * @param {Function} [callback] an optional callback fn * @return {undefined} */ -Reissue.prototype.stop = function stop() { +Reissue.prototype.stop = function stop(callback) { + + assert.optionalFunc(callback, 'callback'); + var self = this; - self._active = false; + + // if not currently active, do nothing. if callback available call it. + if (self._active === false) { + if (callback) { + self._stopCallback = callback; + callback(); + } + } else { + // if active, set active flag to false. + self._active = false; + + // save the callback for invocation. + if (callback) { + self._stopCallback = callback; + } + } + }; diff --git a/test/index.js b/test/index.js index fc96ab2..785f9ea 100644 --- a/test/index.js +++ b/test/index.js @@ -383,4 +383,79 @@ describe('Reissue module', function() { return done(); }, 500); }); + + + it('should call callback if stop called when already inactive', + function(done) { + + var timer = reissue.create({ + func: function(callback) { + return callback(); + }, + interval: 100 + }); + timer.stop(done); + }); + + + it('should call stop callback on completion when stop is called pre ' + + 'function invocation', function(done) { + + var out = []; + var i = 0; + + var timer = reissue.create({ + func: function(callback) { + out.push(i); + i += 1; + return callback(); + }, + interval: 100 + }); + timer.start(); + + setTimeout(function() { + timer.stop(function() { + assert.deepEqual(out, [0,1,2]); + return done(); + }); + }, 300); + }); + + + it('should call stop callback on completion when stop is called mid ' + + 'function invocation', function(done) { + + var count = 0; + + // attempt run this only through one cycle + var timer = reissue.create({ + func: function(callback) { + + count++; + var i = 0; + + while (true) { // eslint-disable-line no-constant-condition + i++; + + if (i === 100000) { + break; + } + } + + return callback(); + }, + interval: 1000 + }); + + + setImmediate(function() { + timer.stop(function() { + assert.equal(count, 1); + return done(); + }); + }); + + timer.start(); + }); });