{"id":18952531,"url":"https://github.com/jdan/alock","last_synced_at":"2026-03-15T10:53:06.451Z","repository":{"id":13090219,"uuid":"15771467","full_name":"jdan/alock","owner":"jdan","description":"Arbitrary locking mechanism for asynchronous operations","archived":false,"fork":false,"pushed_at":"2014-01-10T16:51:06.000Z","size":138,"stargazers_count":28,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-08-31T15:57:15.803Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-01-09T16:04:48.000Z","updated_at":"2024-02-04T05:46:22.000Z","dependencies_parsed_at":"2022-09-01T14:21:38.700Z","dependency_job_id":null,"html_url":"https://github.com/jdan/alock","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdan%2Falock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdan%2Falock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdan%2Falock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdan%2Falock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdan","download_url":"https://codeload.github.com/jdan/alock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223692287,"owners_count":17186982,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T13:33:51.833Z","updated_at":"2026-03-15T10:53:01.418Z","avatar_url":"https://github.com/jdan.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## alock\n\nArbitrary locking mechanism for asynchronous operations\n\n### About\n\n    npm install alock\n\nThis module is an event-based approach to locking asynchronous operations.\nLocks are established and freed on a key-by-key basis and are passed two\narguments: a key to uniquely identify the operation you want to lock, and a\ncallback.\n\nThis callback should accept a function – `done()` – which, when invoked, frees\nthe lock.\n\nLet's give it a whirl.\n\n### Usage\n\n```javascript\nvar lock = require('alock');\n\nlock(\"console-log\", function (done) {\n  setTimeout(function () {\n    console.log('First!');\n    done();\n  }, 1000);\n});\n\nlock(\"console-log\", function (done) {\n  setImmediate(function () {\n    console.log('Second!');\n    done();\n  });\n});\n```\n\nWithout locking, the above example would normally print \"Second!\" followed by\n\"First!\" a second later. Instead, we see a 1-second delay, followed by both\n\"First!\" and \"Second!\" displaying in quick succession.\n\n**alock** can be used to simulate atomic operations on virtually anything.\nConsider the following example: We want to fetch some serialized object from\na key-value store, change one of its properties, and place it back. If two of\nthese operations are called in quick succession, one of the operations may\nreceive an outdated copy of this object because of a\n[race condition](http://en.wikipedia.org/wiki/Race_condition). Instead, let's\nlock the operation to prevent such a data hazard.\n\n```javascript\nlock(\"double-score\", function (done) {\n  db.get('player1', function (err, value) {\n    value = JSON.parse(value);\n    value.score *= 2;\n    db.put('player1', JSON.stringify(value), function (err) {\n      done();\n    });\n  });\n});\n```\n\n### How it Works\n\n**alock** uses node's built-in `EventEmitter` class at its core. The internal\nlocks object holds EventEmitter instances, each responsible for emitting a\n\"free\" event when the operation has completed.\n\nWhen `lock()` is called, the library checks to see if the key already has a lock\non it – that is – that the internal locks object holds the key. If such a\nlock already exists, we create an event listener for the \"free\" event to then\nacquire the lock ourselves.\n\nTo acquire a lock means to assign a new EventEmitter instance to the key in\nthe internal locks object, then invoke the callback originally passed to us.\n\n[The source is around 30 lines](https://github.com/jdan/alock/blob/master/index.js),\nso be sure to check it out for yourself.\n\n### License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdan%2Falock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdan%2Falock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdan%2Falock/lists"}