oaeproject/Hilary

View on GitHub
packages/oae-util/lib/counter.js

Summary

Maintainability
A
25 mins
Test Coverage
A
97%
/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

import * as EmitterAPI from 'oae-emitter';

/**
 * A utility structure that allows one to increment and decrement a count, firing bound handlers
 * when the count becomes `0`
 *
 * @function Counter
 * @return {Object}    An object with several functions that manipulate the counter
 */
const Counter = function () {
  let _count = 0;
  const _emitter = new EmitterAPI.EventEmitter();

  const that = {};

  /**
   * Set the current count of the counter to zero
   *
   */
  that.zero = function () {
    _count = 0;
    _emitter.emit('empty');
  };

  /**
   * Get the current count of the counter
   *
   * @return {Number}     The current count
   */
  that.get = function () {
    return _count;
  };

  /**
   * Increment the current count by the provided amount
   *
   * @param  {Number}     [incrBy]    How much to increment the counter by. Default: 1
   */
  that.incr = function (incrBy = 1) {
    _count += incrBy;
  };

  /**
   * Decrement the current count by the provided amount. If decrementing by this amount brings the
   * count down to 0, then whatever handlers are waiting on it to become `0` will be fired. The
   * value of the counter cannot be less than `0`, therefore decrementing an empty counter will
   * result in no change, and no offset for future incrementing
   *
   * @param  {Number}     [decrBy]    How much to decrement the counter by. Default: 1
   */
  that.decr = function (decrBy = 1) {
    // If the count is already "empty", just ensure we're settled at 0 and don't fire any events
    if (_count <= 0) {
      _count = 0;
      return;
    }

    // Decrement by the provided amount, and if we become empty, fire the empty event in case
    // anyone is waiting
    _count -= decrBy;
    if (_count <= 0) {
      _count = 0;
      _emitter.emit('empty');
    }
  };

  /**
   * Fire the given handler when the count becomes `0`. If the count is currently `0`, the handler
   * is fired immediately
   *
   * @param  {Function}       handler     Invoked when the count becomes `0`
   * @returns {EventEmitter}              Returns the promise that the `handler` function will be called once for the `empty` event
   */
  that.whenZero = function (handler) {
    if (_count <= 0) {
      return handler();
    }

    return _emitter.once('empty', handler);
  };

  return that;
};

export { Counter as default };