mapLimit() Async Function

Implement a mapLimit function that is similar to the Array.map() which returns a promise that resolves on the list of output by mapping each input through an asynchronous iteratee function or rejects it if any error occurs. It also accepts a limit. Based on the limit the input array will be chopped. Each chopped array will be executed in Sequence and values inside chopped array will be executed in Parallel.

function chop(array, limit) {
  const results = [];
  let index = 0;
  while (index < array.length) {
    results.push(array.slice(index, index + limit));
    index = index + limit;
  }
  return results;
}

function mapLimit(inputs, limit, iterateeFn, callback) {
  const choppedInputs = chop(inputs, limit);
  let finalResult = choppedInputs.reduce((prev, curr) => {
    return prev.then((val) => {
      return new Promise((resolve, reject) => {
        let asyncParallel = [];
        curr.forEach((ele) => {
          iterateeFn(ele, (userId) => {
            asyncParallel.push(userId);

            if (asyncParallel.length === curr.length) {
              resolve([...val, ...asyncParallel]);
            }
          });
        });
      });
    });
  }, Promise.resolve([]));
  finalResult.then((res) => callback(res));
}
function getNameById(id, callback) {
  const randomRequestTime = Math.floor(Math.random() * 100) + 200;
  setTimeout(() => {
    callback("User" + id);
  }, randomRequestTime);
}

mapLimit([1, 2, 3, 4, 5], 2, getNameById, (allResults) =>
  console.log(allResults)
);
// [ 'User2', 'User1', 'User4', 'User3', 'User5' ]

mapLimit([1, 2, 3, 4, 5], 2, getNameById, (allResults) =>
  console.log(allResults)
);
// [ 'User1', 'User2', 'User4', 'User3', 'User5' ]

mapLimit([1, 2, 3, 4, 5], 2, getNameById, (allResults) =>
  console.log(allResults)
);
// [ 'User1', 'User2', 'User3', 'User4', 'User5' ]