Weird API to release the lock. What if you want to hold on to it? Then you need to do some silly promise wrapper. Would be better if there was a matching release() function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
I'm not sure why Web Locks is useful TBH. I guess if you don't understand atomics it's a friendlier API?
”[…] allows a web app running in multiple tabs or workers to coordinate work and the use of resources”
A locking API is much more natural and less error-prone for this use case than using shared memory and atomics.
If the atomics API gave you ability to do multiple things, you wouldn't need compareExchange, because you could just do compare and then exchange.
p = Promise.withResolvers()
navigator.locks.request(
"foo",
p.promise,
)
p.resolve()
I guess there’s room for .requestWithResolvers() still, they rarely learn the first lesson. Even the $subj article seems to be unaware of it and uses the silly wrapper way. class Lock {
#release: () => void | undefined;
constructor(public name: string) {}
acquire() {
if (this.#release !== undefined) throw new Error("Already locked");
navigator.locks.request(this.name, async (lock) => {
await new Promise<void>(resolve => {
this.#release = resolve;
});
});
}
release() {
if (this.#release === undefined) throw new Error("Not locked");
this.#release();
}
} class Lock {
#resolve: (() => void) | undefined;
#releasePromise: Promise<void> | undefined;
constructor(public name: string) {}
acquire(): Promise<void> {
if (this.#releasePromise !== undefined) {
throw new Error("Already aquired");
}
return new Promise((resolveAquire, _rejectAquire) => {
this.#releasePromise = new Promise((resolveRelease, _rejectRelease) => {
navigator.locks.request(this.name, async (lock) => {
await new Promise<void>((resolve, _reject) => {
this.#resolve = resolve;
resolveAquire();
});
resolveRelease();
});
});
});
}
async release(): Promise<void> {
if (this.#releasePromise === undefined) {
throw new Error("Already released");
}
this.#resolve();
await this.#releasePromise;
this.#resolve = undefined;
this.#releasePromise = undefined;
}
}
...the release phase still feels off without a Promise, but maybe somebody else can tackle that :DEDIT: think I fixed it, untested though