private-async-helpers.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /**
  2. * @license
  3. * Copyright 2021 Google LLC
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. // Note, this module is not included in package exports so that it's private to
  7. // our first-party directives. If it ends up being useful, we can open it up and
  8. // export it.
  9. /**
  10. * Helper to iterate an AsyncIterable in its own closure.
  11. * @param iterable The iterable to iterate
  12. * @param callback The callback to call for each value. If the callback returns
  13. * `false`, the loop will be broken.
  14. */
  15. export const forAwaitOf = async (iterable, callback) => {
  16. for await (const v of iterable) {
  17. if ((await callback(v)) === false) {
  18. return;
  19. }
  20. }
  21. };
  22. /**
  23. * Holds a reference to an instance that can be disconnected and reconnected,
  24. * so that a closure over the ref (e.g. in a then function to a promise) does
  25. * not strongly hold a ref to the instance. Approximates a WeakRef but must
  26. * be manually connected & disconnected to the backing instance.
  27. */
  28. export class PseudoWeakRef {
  29. constructor(ref) {
  30. this._ref = ref;
  31. }
  32. /**
  33. * Disassociates the ref with the backing instance.
  34. */
  35. disconnect() {
  36. this._ref = undefined;
  37. }
  38. /**
  39. * Reassociates the ref with the backing instance.
  40. */
  41. reconnect(ref) {
  42. this._ref = ref;
  43. }
  44. /**
  45. * Retrieves the backing instance (will be undefined when disconnected)
  46. */
  47. deref() {
  48. return this._ref;
  49. }
  50. }
  51. /**
  52. * A helper to pause and resume waiting on a condition in an async function
  53. */
  54. export class Pauser {
  55. constructor() {
  56. this._promise = undefined;
  57. this._resolve = undefined;
  58. }
  59. /**
  60. * When paused, returns a promise to be awaited; when unpaused, returns
  61. * undefined. Note that in the microtask between the pauser being resumed
  62. * an an await of this promise resolving, the pauser could be paused again,
  63. * hence callers should check the promise in a loop when awaiting.
  64. * @returns A promise to be awaited when paused or undefined
  65. */
  66. get() {
  67. return this._promise;
  68. }
  69. /**
  70. * Creates a promise to be awaited
  71. */
  72. pause() {
  73. var _a;
  74. (_a = this._promise) !== null && _a !== void 0 ? _a : (this._promise = new Promise((resolve) => (this._resolve = resolve)));
  75. }
  76. /**
  77. * Resolves the promise which may be awaited
  78. */
  79. resume() {
  80. var _a;
  81. (_a = this._resolve) === null || _a === void 0 ? void 0 : _a.call(this);
  82. this._promise = this._resolve = undefined;
  83. }
  84. }
  85. //# sourceMappingURL=private-async-helpers.js.map