utils.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.readFile = readFile;
  6. exports.stat = stat;
  7. exports.throttleAll = throttleAll;
  8. function stat(inputFileSystem, path) {
  9. return new Promise((resolve, reject) => {
  10. inputFileSystem.stat(path, (err, stats) => {
  11. if (err) {
  12. reject(err);
  13. }
  14. resolve(stats);
  15. });
  16. });
  17. }
  18. function readFile(inputFileSystem, path) {
  19. return new Promise((resolve, reject) => {
  20. inputFileSystem.readFile(path, (err, stats) => {
  21. if (err) {
  22. reject(err);
  23. }
  24. resolve(stats);
  25. });
  26. });
  27. }
  28. const notSettled = Symbol(`not-settled`);
  29. /**
  30. * Run tasks with limited concurency.
  31. * @template T
  32. * @param {number} limit - Limit of tasks that run at once.
  33. * @param {Task<T>[]} tasks - List of tasks to run.
  34. * @returns {Promise<T[]>} A promise that fulfills to an array of the results
  35. */
  36. function throttleAll(limit, tasks) {
  37. if (!Number.isInteger(limit) || limit < 1) {
  38. throw new TypeError(`Expected \`limit\` to be a finite number > 0, got \`${limit}\` (${typeof limit})`);
  39. }
  40. if (!Array.isArray(tasks) || !tasks.every(task => typeof task === `function`)) {
  41. throw new TypeError(`Expected \`tasks\` to be a list of functions returning a promise`);
  42. }
  43. return new Promise((resolve, reject) => {
  44. const result = Array(tasks.length).fill(notSettled);
  45. const entries = tasks.entries();
  46. const next = () => {
  47. const {
  48. done,
  49. value
  50. } = entries.next();
  51. if (done) {
  52. const isLast = !result.includes(notSettled);
  53. if (isLast) {
  54. resolve(
  55. /** @type{T[]} **/
  56. result);
  57. }
  58. return;
  59. }
  60. const [index, task] = value;
  61. /**
  62. * @param {T} x
  63. */
  64. const onFulfilled = x => {
  65. result[index] = x;
  66. next();
  67. };
  68. task().then(onFulfilled, reject);
  69. };
  70. Array(limit).fill(0).forEach(next);
  71. });
  72. }