Skip to content

Instantly share code, notes, and snippets.

@creationix
Last active April 22, 2020 03:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save creationix/590fe6e3f3e511b41217be0aa2a77692 to your computer and use it in GitHub Desktop.
Save creationix/590fe6e3f3e511b41217be0aa2a77692 to your computer and use it in GitHub Desktop.
const locks = {};
async function protect(fn, name, ...args) {
while (locks[name]) await locks[name]
return (locks[name] = new Promise(async (resolve) => {
const ret = await fn(name, ...args);
delete locks[name];
resolve(ret);
}));
}
//////////////////////////////////////////////////////////
async function unsafeWork(key) {
// Simulate doing work
console.log(key, "Start");
await new Promise(resolve => setTimeout(resolve, 100));
console.log(key, "End");
return `Returned from ${key}`;
}
function safeWork(key) {
return protect(unsafeWork, key);
}
safeWork(1).then(console.log);
safeWork(2).then(console.log);
safeWork(1).then(console.log);
safeWork(2).then(console.log);
safeWork(3).then(console.log);
safeWork(3).then(console.log);
safeWork(1).then(console.log);
@creationix
Copy link
Author

If you call unsafeWork directly, it looks like:

1 Start
2 Start
1 Start
2 Start
3 Start
3 Start
1 Start
1 End
2 End
1 End
2 End
3 End
3 End
1 End

But with safeWork, you never have concurrent calls on the same key:

1 Start
2 Start
3 Start
1 End
1 Start
2 End
2 Start
3 End
3 Start
1 End
1 Start
2 End
3 End
1 End

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