Skip to content

Instantly share code, notes, and snippets.

@jpwilliams
Last active April 25, 2018 12:27
Show Gist options
  • Save jpwilliams/98bd667e03eeaab37b704f8e7d14bf5d to your computer and use it in GitHub Desktop.
Save jpwilliams/98bd667e03eeaab37b704f8e7d14bf5d to your computer and use it in GitHub Desktop.
A promise-based locking mechanism.

Usage

// create a new lock
const locker = new Locker()

// wait for lock
const releaseLock = await locker.waitForLock()

// we have the lock! do stuff

// release the lock
releaseLock()
export class Locker {
constructor () {
this._locked = false
this._waiting = []
}
waitForLock (opts = {}) {
if (!this._locked) {
this._locked = true
return Promise.resolve(this._getReleaser())
}
const { timeout = 0 } = opts
return new Promise((resolve, reject) => {
const releaser = () => resolve(this._getReleaser())
this._waiting.push(releaser)
if (timeout) {
setTimeout(() => {
this._clearFn(releaser)
reject(new Error('Timed out'))
}, timeout)
}
})
}
_getReleaser () {
let released = false
return () => {
if (released) return
released = true
const next = this._waiting.shift()
if (next) {
next()
return
}
this._locked = false
}
}
_clearFn (fn) {
const idx = this._waiting.indexOf(fn)
if (idx > -1) this._waiting.splice(idx, 1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment