async-fifo-queue.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. "use strict";
  2. /**
  3. * (c) 2017-2025 BullForce Labs AB, MIT Licensed.
  4. * @see LICENSE.md
  5. *
  6. */
  7. Object.defineProperty(exports, "__esModule", { value: true });
  8. exports.AsyncFifoQueue = void 0;
  9. class Node {
  10. constructor(value) {
  11. this.value = undefined;
  12. this.next = null;
  13. this.value = value;
  14. }
  15. }
  16. class LinkedList {
  17. constructor() {
  18. this.length = 0;
  19. this.head = null;
  20. this.tail = null;
  21. }
  22. push(value) {
  23. const newNode = new Node(value);
  24. if (!this.length) {
  25. this.head = newNode;
  26. }
  27. else {
  28. this.tail.next = newNode;
  29. }
  30. this.tail = newNode;
  31. this.length += 1;
  32. return newNode;
  33. }
  34. shift() {
  35. if (!this.length) {
  36. return null;
  37. }
  38. else {
  39. const head = this.head;
  40. this.head = this.head.next;
  41. this.length -= 1;
  42. return head;
  43. }
  44. }
  45. }
  46. /**
  47. * AsyncFifoQueue
  48. *
  49. * A minimal FIFO queue for asynchronous operations. Allows adding asynchronous operations
  50. * and consume them in the order they are resolved.
  51. */
  52. class AsyncFifoQueue {
  53. constructor(ignoreErrors = false) {
  54. this.ignoreErrors = ignoreErrors;
  55. /**
  56. * A queue of completed promises. As the pending
  57. * promises are resolved, they are added to this queue.
  58. */
  59. this.queue = new LinkedList();
  60. /**
  61. * A set of pending promises.
  62. */
  63. this.pending = new Set();
  64. this.newPromise();
  65. }
  66. add(promise) {
  67. this.pending.add(promise);
  68. promise
  69. .then(data => {
  70. this.pending.delete(promise);
  71. if (this.queue.length === 0) {
  72. this.resolvePromise(data);
  73. }
  74. this.queue.push(data);
  75. })
  76. .catch(err => {
  77. // Ignore errors
  78. if (this.ignoreErrors) {
  79. this.queue.push(undefined);
  80. }
  81. this.pending.delete(promise);
  82. this.rejectPromise(err);
  83. });
  84. }
  85. async waitAll() {
  86. await Promise.all(this.pending);
  87. }
  88. numTotal() {
  89. return this.pending.size + this.queue.length;
  90. }
  91. numPending() {
  92. return this.pending.size;
  93. }
  94. numQueued() {
  95. return this.queue.length;
  96. }
  97. resolvePromise(data) {
  98. this.resolve(data);
  99. this.newPromise();
  100. }
  101. rejectPromise(err) {
  102. this.reject(err);
  103. this.newPromise();
  104. }
  105. newPromise() {
  106. this.nextPromise = new Promise((resolve, reject) => {
  107. this.resolve = resolve;
  108. this.reject = reject;
  109. });
  110. }
  111. async wait() {
  112. return this.nextPromise;
  113. }
  114. async fetch() {
  115. var _a;
  116. if (this.pending.size === 0 && this.queue.length === 0) {
  117. return;
  118. }
  119. while (this.queue.length === 0) {
  120. try {
  121. await this.wait();
  122. }
  123. catch (err) {
  124. // Ignore errors
  125. if (!this.ignoreErrors) {
  126. console.error('Unexpected Error in AsyncFifoQueue', err);
  127. }
  128. }
  129. }
  130. return (_a = this.queue.shift()) === null || _a === void 0 ? void 0 : _a.value;
  131. }
  132. }
  133. exports.AsyncFifoQueue = AsyncFifoQueue;
  134. //# sourceMappingURL=async-fifo-queue.js.map