JSFiddle - React, Tailwind, and code Playground

HTML

<div id="main">
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

CSS

#main {
  display: flex;
}

.block {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
  margin: 10px;
  width: 150px;
  height: 150px;
  border: solid;
}

JavaScript

function doGo(it, options = {}) {
  const {
    resolve,
    reject,
    onYield,
    minTimeRemaining,
  } = options;
  requestIdleCallback(deadline => {
    try {
      let val = it.next()
      while (!val.done) {
        onYield && onYield(val.value);
        if (deadline.timeRemaining() <= minTimeRemaining) {
          doGo(it, options)
          return
        }
        val = it.next()
      }
      resolve(val.value)
    } catch (e) {
      reject(e)
    }
  })
}

function go(it, {
  onYield,
  minTimeRemaining = 0
}) {
  return new Promise((resolve, reject) => {
    doGo(it, {
      resolve,
      reject,
      onYield,
      minTimeRemaining
    })
  })
}






function* summation(x, {
  batchSize = 1000
} = {}) {
  let i = x,
    ret = 1
  while (i > 1) {
    ret += i
    i--
    if (i % batchSize === 0) {
      yield(x - i) / x
    }
  }
  return ret
}


function setResult(index, html) {
  document.querySelectorAll('.block')[index].innerHTML = html;
}

function startSummation(index, x, options) {
  go(summation(x, options), {
    onYield: progress => setResult(index, (progress * 100) + "%")
  }).then(
    result => setResult(index, "END"),
    error => setResult(index, "ERROR")
  )
}

startSummation(0, 100000000, {
  batchSize: 100
})
startSummation(1, 100000000, {
  batchSize: 1000
})
startSummation(2, 100000000, {
  batchSize: 10000
})