JSFiddle - React, Tailwind, and code Playground

JavaScript

async function* makeALotOfWork() {
	let id = 0;
  while (true) {
  	yield ({ id: id++, delay: Math.floor(Math.random() * 1000) + 10 });
  }
}

function makeWork(t) {
	t.promise = new Promise(resolve => setTimeout(() => resolve(t), t.delay));
  return t;
}

async function* map(tasks, n) {
  try {
    // Start n work
    const parallel = new Set();
    for (let i = 0; i < n; ++i) {
    	const itr = await tasks.next();
      if (itr.done) return;
    	parallel.add(makeWork(itr.value));
    }
    // Process the work yielding the first one done in the set of n work
	  while (parallel.length != 0) {
  	  const task = await Promise.race([...parallel].map(t => t.promise));
      parallel.delete(task);
      yield task;
      // Add 1 more work
      const itr = await tasks.next();
      if (itr.done) return;
      parallel.add(makeWork(itr.value));
    }
  } finally {
    console.log('map done');
    tasks?.return();
  }
}

(async () => {
  let workDone = 0;
  for await (const t of map(map(makeALotOfWork(), 5), 5)) {
  	console.log(t.id, t.delay);
    workDone++;
    if (workDone > 10) {
      break;
    }
  }
})();