promisen.js
function throttle(task, concurrency, timeout) {
    if (!concurrency) concurrency = 1;
    task = promisen(task);
    var queue = singleTask.queue = [];
    var running = singleTask.running = {};
    var serial = 0;
    return singleTask;

    function singleTask(value) {
      var that = this;
      var args = arguments;
      var Promise = promisen.Promise;
      var seq = ++serial;

      return new Promise(function(resolve, reject) {
        queue.push(job);
        var timer = timeout && setTimeout(onTimeout, timeout);
        next();

        function job() {
          if (timer) clearTimeout(timer);
          running[seq] = true;
          task.apply(that, args).then(onResolve, onReject);
        }

        function onTimeout() {
          onReject(new Error("timeout: " + timeout + "ms"));
        }

        function onResolve(value) {
          delete running[seq];
          setTimeout(next, 0);
          resolve(value);
        }

        function onReject(value) {
          delete running[seq];
          setTimeout(next, 0);
          reject(value);
        }
      });
    }

    function next() {
      if (Object.keys(running).length >= concurrency) return;
      var job = queue.pop();
      if (job) job();
    }
  }
function throttle(task, concurrency, timeout) {
    if (!concurrency) concurrency = 1;
    task = promisen(task);
    var queue = singleTask.queue = [];
    var running = singleTask.running = {};
    var serial = 0;
    return singleTask;

    function singleTask(value) {
      var that = this;
      var args = arguments;
      var Promise = promisen.Promise;
      var seq = ++serial;

      return new Promise(function(resolve, reject) {
        queue.push(job);
        var timer = timeout && setTimeout(onTimeout, timeout);
        next();

        function job() {
          if (timer) clearTimeout(timer);
          running[seq] = true;
          task.apply(that, args).then(onResolve, onReject);
        }

        function onTimeout() {
          onReject(new Error("timeout: " + timeout + "ms"));
        }

        function onResolve(value) {
          delete running[seq];
          setTimeout(next, 0);
          resolve(value);
        }

        function onReject(value) {
          delete running[seq];
          setTimeout(next, 0);
          reject(value);
        }
      });
    }

    function next() {
      if (Object.keys(running).length >= concurrency) return;
      var job = queue.pop();
      if (job) job();
    }
  }
function throttle ( task , concurrency , timeout ) { if ( ! concurrency ) concurrency = 1 ; task = promisen ( task ) ; var queue = singleTask . queue = [ ] ; var running = singleTask . running = { } ; var serial = 0 ; return singleTask ; function singleTask ( value ) { var that = this ; var args = arguments ; var Promise = promisen . Promise ; var seq = ++ serial ; return new Promise ( function ( resolve , reject ) { queue . push ( job ) ; var timer = timeout && setTimeout ( onTimeout , timeout ) ; next ( ) ; function job ( ) { if ( timer ) clearTimeout ( timer ) ; running [ seq ] = true ; task . apply ( that , args ) . then ( onResolve , onReject ) ; } function onTimeout ( ) { onReject ( new Error ( "timeout: " + timeout + "ms" ) ) ; } function onResolve ( value ) { delete running [ seq ] ; setTimeout ( next , 0 ) ; resolve ( value ) ; } function onReject ( value ) { delete running [ seq ] ; setTimeout ( next , 0 ) ; reject ( value ) ; } } ) ; } function next ( ) { if ( Object . keys ( running ) . length >= concurrency ) return ; var job = queue . pop ( ) ; if ( job ) job ( ) ; } }
creates a promise-returning function which limits number of concurrent job workers run in parallel.

@class promisen
@static
@function throttle
@param task {Function} the job
@param concurrency {Number} number of job workers run in parallel (default: 1)
@param timeout {Number} timeout in millisecond until job started (default: no timeout)
@returns {Function} promise-returning function
@example
var promisen = require("promisen");

var serialAjaxTask = promisen.throttle(ajaxTask, 1, 10000); // 1 worker, 10 seconds

serialAjaxTask(req).then(function(res) {...});
creates a promise - returning function which limits number of concurrent job workers run in parallel .