Skip to content

Instantly share code, notes, and snippets.

@epreston
Created April 28, 2023 21:10
Show Gist options
  • Save epreston/6dd95501df9fba679809ec2802c3bbbd to your computer and use it in GitHub Desktop.
Save epreston/6dd95501df9fba679809ec2802c3bbbd to your computer and use it in GitHub Desktop.
promise based semaphore - caller controllable promise interface
function Semaphore() {
// controllable promise
let _resolve;
let _reject;
const promiseSemaphore = new Promise((resolve, reject) => {
_resolve = resolve;
_reject = reject;
});
promiseSemaphore.resolve = _resolve;
promiseSemaphore.reject = _reject;
return promiseSemaphore;
}
@epreston
Copy link
Author

This is used to simplify resource management or resource initialisation.

First caller will await completion. Other callers will get the promise interface to either wait as well or continue immediately.

await load();

await Promise.all([
  load(),
  load(),
  load(),
]);

Example for something that may need to be awaited but can run again.

let loadingPromise = null;

async function load() {
  if (loadingPromise) return loadingPromise;

  loadingPromise = Semaphore();

  // do important work, with a number of callers waiting

  // notify everything awaiting the completion
  loadingPromise.resolve();

  // allow this to be run again
  loadingPromise = null;
}

For something that should only be run once, don't reset the promise variable.

let loadingPromise = null;

async function load(e) {
  if (loadingPromise) return loadingPromise;

  loadingPromise = Semaphore();

  // do important work once (load a resource from the API)

  // notify everything awaiting the completion
  loadingPromise.resolve();

  // anything requesting this again will get a resolved promise and continue.
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment