{"id":15646429,"url":"https://github.com/martinheidegger/flexlock-cb","last_synced_at":"2025-03-29T23:17:16.422Z","repository":{"id":57238322,"uuid":"164026291","full_name":"martinheidegger/flexlock-cb","owner":"martinheidegger","description":"A locking library like mutexify, mutex-js, await-lock, and many more, but with more flexibility in how to use it to be both sturdier and very quick.","archived":false,"fork":false,"pushed_at":"2020-10-13T07:48:10.000Z","size":73,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-12T06:15:18.955Z","etag":null,"topics":["javascript","lock","multithreading","mutex","mutex-lock","process"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/martinheidegger.png","metadata":{"files":{"readme":"Readme.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-03T21:46:30.000Z","updated_at":"2020-10-13T07:47:24.000Z","dependencies_parsed_at":"2022-08-26T14:13:03.151Z","dependency_job_id":null,"html_url":"https://github.com/martinheidegger/flexlock-cb","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinheidegger%2Fflexlock-cb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinheidegger%2Fflexlock-cb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinheidegger%2Fflexlock-cb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinheidegger%2Fflexlock-cb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinheidegger","download_url":"https://codeload.github.com/martinheidegger/flexlock-cb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245708986,"owners_count":20659625,"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":["javascript","lock","multithreading","mutex","mutex-lock","process"],"created_at":"2024-10-03T12:12:51.361Z","updated_at":"2025-03-29T23:17:16.398Z","avatar_url":"https://github.com/martinheidegger.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# flexlock-cb\n\n[![Build Status][cistatus-img]][cistatus-lnk]\n[![JavaScript Style Guide][js-style-img]](https://standardjs.com)\n[![Maintainability][maintain-img]][maintain-lnk]\n[![Test Coverage][coverage-img]][coverage-lnk]\n\n[cistatus-lnk]: https://travis-ci.org/martinheidegger/flexlock-cb\n[cistatus-img]: https://travis-ci.org/martinheidegger/flexlock-cb.svg?branch=master\n[js-style-img]: https://img.shields.io/badge/code_style-standard-brightgreen.svg\n[maintain-img]: https://api.codeclimate.com/v1/badges/0515ec5a0831b36b5992/maintainability\n[maintain-lnk]: https://codeclimate.com/github/martinheidegger/flexlock-cb/maintainability\n[coverage-img]: https://api.codeclimate.com/v1/badges/0515ec5a0831b36b5992/test_coverage\n[coverage-lnk]: https://codeclimate.com/github/martinheidegger/flexlock-cb/test_coverage\n\n`flexlock-cb` is a **very small**, **memory-concious**, **flexible** locking library without\ndependencies but with `typescript` definitions (see in the bottom). Optimized even further than\n[`flexlock`][flexlock] for the use with callbacks instead of promises.\n\n`npm i flexlock-cb --save`\n\nIt is similar to other in-memory locking library like [`mutexify`][mutexify],\n[`mutex-js`][mutex-js], [`await-lock`][await-lock], and [many more](many-more),\nbut with more flexibility in how to use it.\n\nThis makes it sturdier and more practical in many cases.\n\n[flexlock]: https://github.com/martinheidegger/flexlock\n[mutexify]: https://github.com/mafintosh/mutexify\n[mutex-js]: https://github.com/danielglennross/mutex-js\n[await-lock]: https://www.npmjs.com/package/await-lock\n[many-more]: https://www.npmjs.com/search?q=promise+lock\n\n### _simple_ basic API\n\n```javascript\nconst { createLockCb } = require('flexlock-cb')\n\nconst lock = createLockCb()\n\nlock(unlock =\u003e {\n  // done before the next block\n  unlock()\n})\nlock(unlock =\u003e {\n  // will wait for the \n  unlock()\n})\n```\n\n### _Propagation_ of errors and results to a callback\n\n```javascript\nfunction callback (err, data) {\n  // err === null\n  // data === 'important'\n}\n\nlock(\n  unlock =\u003e unlock(null, 'important'),\n  callback\n)\n```\n\n### _Promises_ are returned if no callback is added\n\n```javascript\nconst promise = lock(unlock =\u003e {\n  unlock(null, 'important')\n}) // Without passing in a callback, promises will be created\n\npromise\n  .catch(err =\u003e {})\n  .then(data =\u003e {})\n  // This way you can support both callback and promise based APIs\n```\n\n### _Timeouts_ in case anther lock never returns\n\n```javascript\nfunction neverUnlock (unlock) { /* Due to a bug it never unlocks */ }\nfunction neverCalled () {}\n\nlock(neverUnlock)\nlock(neverCalled, 500, err =\u003e {\n  err.code === 'ETIMEOUT'\n})\n```\n\n### _release_ handlers both once and for every release\n\n```javascript\nfunction onEveryRelease () {}\nfunction onNextRelease () {}\n\nconst lock = createLockCb(onEveryRelease) // Called everytime the lock is released\nlock.released(onNextRelease) // Called next time the lock is released\n\nawait lock.released() // Promise API available as well\n```\n\n### Like for Promises, two separate callbacks can be specified\n\n```javascript\nfunction onSuccess (data) {}\nfunction onError (err) {}\n\nlock(unlock =\u003e unlock(), onSucess, onError)\n```\n\n### _sync_ handlers, for when you want to make sure that other locks are done\n\n```javascript\nconst lock = createLockCb()\n\nconst result = await lock.sync(() =\u003e {\n  // no unlock function (automatically unlocked after method is done)\n  return 123\n})\n\nresult === 123 // the result is passed to the callback\n```\n\nIn case you need it, a reference to the lock is also passed in:\n\n```javascript\nconst result = await lock.sync(lock =\u003e { /* ... */ })\n```\n\nIts also possible to wrap a method into a sync lock:\n\n```javascript\nconst fn = lock.syncWrap((foo, bar) =\u003e {\n  /**\n   - No unlock function.\n   - Arguments are passed-through.\n   - Executed will be asynchronously.\n   - Return value will be ignored.\n   */\n  foo === 'hello'\n  bar === 'world'\n})\nfn('hello', 'world')\n```\n\nBe aware that any errors that might occur will by-default result in uncaught\nexceptions!\n\nYou can handle those errors by passing an error handler when creating the lock:\n\n```javascript\nconst lock = createLockCb(null, err =\u003e {\n  // Here you can handle any error, for example: emit('error', err)\n})\nconst fn = lock.syncWrap(() =\u003e {\n  throw new Error('error')\n})\n```\n\n... or by adding a error handler directly when wrapping:\n\n```javascript\nconst fn2 = lock.syncWrap(() =\u003e {\n  throw new Error('error')\n}, err =\u003e {\n  // Handle an error thrown in the sync-wrap\n})\n```\n\n### Destroying locks\n\nWhen closing down an application you may want to also close all operations and prevent\nfuture operations:\n\n```javascript\nimport { createLockCb } from 'flexlock-cb'\n\nconst lock = createLockCb()\nlock.destroy(new Error('lock destroyed') /* optional */)\ntry {\n  lock(cb =\u003e {\n    // will not be executed\n  })\n} catch (err) {\n  // err ... will be the error passed-in to .destroy()\n}\n```\n\n### Typescript recommendation\n\nFiguring out the proper typing was quite tricky for flexlock-cb.\nTo make things easier for users, it exports a `Callbacks` type that\ncan be used to reduce  \n\n```typescript\nimport { Callbacks, createLockCb } from 'flexlock-cb'\n\nconst lock = createLockCb()\n\n//\n// Overloading for the two use cases (return type void or Promise)\n// If you would like to improve this, vote for\n// https://github.com/Microsoft/TypeScript/issues/29182\n//\nfunction fn (foo: string, bar: number, ...cb: Callbacks\u003cstring\u003e): void\nfunction fn (foo: string, bar: number): Promise\u003cstring\u003e\nfunction fn (foo: string, bar: number, ...cb) {\n  return lock(() =\u003e `${foo} ${bar}`, 0, ...cb)\n}\n\n// Separate definitions with the support for timeouts\nimport { CallbacksWithTimeout } from 'flexlock-cb'\n\nfunction fnTime (foo: string, bar: number, ...cb: CallbacksWithTimeout\u003cstring\u003e): void\nfunction fnTime (foo: string, bar: number, timeout?: number): Promise\u003cstring\u003e\nfunction fnTime (foo: string, bar: number, ...cb) {\n  return lock(() =\u003e `${foo} ${bar}`, ...cb)\n}\n```\n\n### License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinheidegger%2Fflexlock-cb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinheidegger%2Fflexlock-cb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinheidegger%2Fflexlock-cb/lists"}