docs: 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();
      }
    }