Promise pool example

by Julien Roche

HTML

<section>
  <h1>Concurrency = 3</h1>
  <button id="runConccurency3">Run</button>
  <ul id="conccurency3"></ul>
</section>
<br />
<section>
  <h1>Concurrency = 10</h1>
  <button id="runConccurency10">Run</button>
  <ul id="conccurency10"></ul>
</section>
<br />
<section>
  <h1>Concurrency = 1</h1>
  <button id="runConccurency1">Run</button>
  <ul id="conccurency1"></ul>
</section>

Babel + JSX

function promisePool(producer, concurrency = 10) {
    return new Promise((resolve, reject) => {
      let index = 0;
      let finished = false;
      let returnedValues = [];
      let nbInstances = concurrency;
      let mainPromise = Promise.resolve();

      function onError(err) {
        if (!finished) {
          finished = true;
          reject(err);
        }
      }

      function onSuccess(value) {
        returnedValues.push(value);

        if (!finished) {
          if (nbInstances < concurrency) {
            nbInstances++;
            process();
          }
        }
      }

      function process() {
        while (!finished && nbInstances > 0) {
          let lastPromise = producer(index);
          index++;
          nbInstances--;

          if (!lastPromise) {
            mainPromise
              .then(() => {
                resolve(returnedValues);
              })
              .catch(onError);

          } else {
            mainPromise = mainPromise
              .then(() => {
              	return lastPromise
                	.then(onSuccess)
              		.catch(onError);
              });
          }
        }
      }

      process();
    });
  }
  
  let ulConccurency1Element = document.querySelector('#conccurency1');
  let ulConccurency3Element = document.querySelector('#conccurency3');
  let ulConccurency10Element = document.querySelector('#conccurency10');
  
  document.querySelector('#runConccurency1').addEventListener('click', event => {
  	event.preventDefault();
    ulConccurency1Element.innerHTML = '';
    
    event.target.disabled = true;
    let html = '';
    
    promisePool(
    	index => {
      	if (index > 20) {
        	return null;
        }
        
        return new Promise(resolve => {
        	setTimeout(
          	() => {
            	let liElement = document.createElement('li');
              liElement.innerText = `Item ${index}`;
              ulConccurency1Element.appendChild(liElement);
         ...