{"id":19932713,"url":"https://github.com/mixmaxhq/lazy-memoize-one","last_synced_at":"2025-05-03T11:32:37.999Z","repository":{"id":33119308,"uuid":"152374933","full_name":"mixmaxhq/lazy-memoize-one","owner":"mixmaxhq","description":"A `memoize-one` wrapper that resolves the latest invocation asynchronously","archived":false,"fork":false,"pushed_at":"2023-11-20T17:15:45.000Z","size":220,"stargazers_count":7,"open_issues_count":3,"forks_count":0,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-04-24T10:03:48.835Z","etag":null,"topics":["supported"],"latest_commit_sha":null,"homepage":"https://www.mixmax.com/careers","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/mixmaxhq.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-10-10T06:37:51.000Z","updated_at":"2022-02-09T18:32:42.000Z","dependencies_parsed_at":"2023-11-20T18:31:34.571Z","dependency_job_id":"4cf0ce6c-9cfa-4bdd-9af3-a8b83366c94d","html_url":"https://github.com/mixmaxhq/lazy-memoize-one","commit_stats":{"total_commits":12,"total_committers":5,"mean_commits":2.4,"dds":0.6666666666666667,"last_synced_commit":"d178f0e019f4ff220d11d273d0f59c9c2e83442b"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mixmaxhq%2Flazy-memoize-one","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mixmaxhq%2Flazy-memoize-one/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mixmaxhq%2Flazy-memoize-one/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mixmaxhq%2Flazy-memoize-one/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mixmaxhq","download_url":"https://codeload.github.com/mixmaxhq/lazy-memoize-one/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252184964,"owners_count":21708057,"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":["supported"],"created_at":"2024-11-12T23:11:20.085Z","updated_at":"2025-05-03T11:32:37.640Z","avatar_url":"https://github.com/mixmaxhq.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lazy-memoize-one\n\nA wrapper around [`memoize-one`] for use with asynchronous functions, that resolves their values\nasynchronously while returning synchronously.\n\n## Rationale\n\n`memoize-one` is a great library until you consider how to use it with asynchronous results:\n\n```js\nimport memoizeOne from 'memoize-one';\n\nconst add = async (a, b) =\u003e a + b;\nconst memoizedAdd = memoizeOne(add);\n\nmemoizedAdd(1, 2); // Promise\n```\n\nThe memoization still _works_\u0026mdash;if you call `memoizedAdd(1, 2)` again it will return the same\n`Promise`, without executing `add` another time\u0026mdash;but it's not very usable anymore: every\ncall to `memoizedAdd` will have to `await` the result of the promise.\n\nIn some cases, it's easier to deal with the result synchronously, if and when it's available; and\nif it's not, retry later. For example, `memoize-one` is often used [in React components], where\nas of React 16.4 `render` executes synchronously, but components can rerun `render` at any time\nby calling `setState`.\n\nIn these cases, you have `lazy-memoize-one`:\n\n```js\nimport memoizeOne from 'lazy-memoize-one';\n\nconst add = async (a, b) =\u003e a + b;\nconst memoizedAdd = memoizeOne(add);\n\nmemoizedAdd(1, 2); // `undefined`\n\n// Wait a turn of the event loop, for `add`'s return value to resolve…\nawait Promise.resolve();\n\nmemoizedAdd(1, 2); // 3\n```\n\nYou can even pass a function as the last argument to the memoized function, to let you know when\nthe result is ready:\n\n```js\nmemoizedAdd(2, 3, (err) =\u003e {\n  if (err) {\n    console.error('Failed to add 2 + 3 for some reason:', err);\n  } else {\n    console.log(`2 + 3 is ${memoizedAdd(2, 3)}`);\n  }\n});\n```\n\n## Installation\n\n```sh\nnpm install lazy-memoize-one\n```\n\n## Usage\n\nFirst, create a memoized function just like `memoize-one`, by passing a function and (optionally)\na [custom equality function]:\n\n```js\nimport memoizeOne from 'lazy-memoize-one'; // or `const memoizeOne = require('lazy-memoize-one');`\n\nconst add = async (a, b) =\u003e a + b;\nconst memoizedAdd = memoizeOne(add);\n```\n\nNote that, in contrast to `memoize-one`, the original function being memoized **must** be an `async`\nfunction. (If it's not, why are you using this library? You'll get synchronous results by using\nregular `memoize-one`.)\n\nNow call the memoized function with the same arguments as you would call the original function.\nYou won't get a `Promise` back, though. Instead, the memoized function will resolve the promise\nbehind the scenes while returning `undefined`, then return the value with which the promise\nresolves:\n\n```js\nmemoizedAdd(1, 2); // `undefined`\n\n// Wait a turn of the event loop, for `add`'s return value to resolve…\nawait Promise.resolve();\n\nmemoizedAdd(1, 2); // 3\n```\n\nIf the promise is rejected, `memoizedAdd` will continue to return `undefined`.\n\nIf you want to know when the promise settles, you can pass a function as the last argument to the\nmemoized function. This function will be called when the promise is resolved or rejected:\n\n```js\nmemoizedAdd(2, 3, (err) =\u003e {\n  if (err) {\n    console.error('The promise was rejected with error:', err);\n  } else {\n    console.log(`2 + 3 is ${memoizedAdd(2, 3)}`);\n  }\n});\n```\n\nThis function will _not_ be called if the memoized function was called with different arguments\nbefore the promise was settled, however, primarily because you wouldn't be able to retrieve the\npromise's result at that point anyway (it will no longer be in the cache).\n\n## Differences from other libraries\n\n### `memoize-one`\n\nRead the [rationale] for the biggest difference from [`memoize-one`]: the ability to memoize\nasynchronous functions but work with their results synchronously.\n\nOther differences:\n\n* the original function being memoized **must** be an `async` function. (If it's not, why are you\n  using this library? You'll get synchronous results by using regular `memoize-one`.)\u003cbr\u003e\u003cbr\u003e\n* there _is_ caching [when your result function throws]. Specifically, the previously-cached value\n  (if any) will be discarded, and the memoized function will return `undefined`. Furthermore, the\n  memoized function will not execute the original function a second time if the memoized function\n  is next called with the same arguments.\n\n  This is primarily a consequence of using `memoize-one` (which this library does, internally) to\n  cache promises, since this means updating the cache before it's known whether doing so will fail.\n  For what it's worth, you would have the same difficulty if you were to use `memoize-one` directly\n  with async functions.\n\n### `lazy-memoize`\n\n[`lazy-memoize`] differs from this library in two big ways. The first is that it caches all the\ncalls you make of it, not just the latest one.\n\nThe second is that it forces you to `await` the cache being initialized. The \"lazy\" part of this\nlibrary is that it returns `undefined` while it's loading, synchronously; then returns the value,\nalso synchronously. The \"lazy\" part of `lazy-memoize` is that it expires the initial values\neventually and then fetches _updated_ values asynchronously, while returning the previous value\nmore quickly.\n\nThis is unacceptable for this library's use case, where access always has to be synchronous, and it\nis ok for the cache to temporarily return `undefined`.\n\n## Contributing / Roadmap\n\nWe welcome bug reports and feature suggestions. PRs are even better!\n\n[`memoize-one`]: https://github.com/alexreardon/memoize-one\n[in React components]: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization\n[custom equality function]: https://github.com/alexreardon/memoize-one#custom-equality-function\n[rationale]: #rationale\n[when your result function throws]: https://github.com/alexreardon/memoize-one#when-your-result-function-throws\n[`lazy-memoize`]: https://github.com/akdor1154/node-lazy-memoize#readme\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmixmaxhq%2Flazy-memoize-one","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmixmaxhq%2Flazy-memoize-one","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmixmaxhq%2Flazy-memoize-one/lists"}