{"id":16392983,"url":"https://github.com/yjl9903/memofunc","last_synced_at":"2025-03-23T04:31:47.352Z","repository":{"id":169328828,"uuid":"639990013","full_name":"yjl9903/memofunc","owner":"yjl9903","description":"Memorize your function call automatically ","archived":false,"fork":false,"pushed_at":"2024-05-03T15:22:06.000Z","size":140,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-01T21:51:11.696Z","etag":null,"topics":["cache","javascript","memorize","optimization","performance","singleton"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/yjl9903.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-12T17:45:16.000Z","updated_at":"2024-05-03T15:22:08.000Z","dependencies_parsed_at":"2023-07-16T08:01:10.074Z","dependency_job_id":"2f58aa50-2a45-4a79-ac7b-5be355ae78c4","html_url":"https://github.com/yjl9903/memofunc","commit_stats":null,"previous_names":["yjl9903/memofunc"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yjl9903%2Fmemofunc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yjl9903%2Fmemofunc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yjl9903%2Fmemofunc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yjl9903%2Fmemofunc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yjl9903","download_url":"https://codeload.github.com/yjl9903/memofunc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244272083,"owners_count":20426666,"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":["cache","javascript","memorize","optimization","performance","singleton"],"created_at":"2024-10-11T04:52:01.436Z","updated_at":"2025-03-23T04:31:47.004Z","avatar_url":"https://github.com/yjl9903.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# memofunc\n\n[![version](https://img.shields.io/npm/v/memofunc?label=memofunc)](https://www.npmjs.com/package/memofunc)\n[![CI](https://github.com/yjl9903/memofunc/actions/workflows/ci.yml/badge.svg)](https://github.com/yjl9903/memofunc/actions/workflows/ci.yml)\n\n**Automatically memorize** your function call. Support **any functions** in JavaScript, zero or more parameters, primitive or reference parameters, sync or async.\n\n+ Support sync function and async function\n+ Use [Trie](https://en.wikipedia.org/wiki/Trie) to map parameter and its return value\n+ Reference object is diffed shallowly with [WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)\n+ Support custom parameter serializaztion method\n+ Support memory and async external cache source at the same time\n+ Support fully external cache source\n\n## Installation\n\n```bash\nnpm i memofunc\n```\n\n## Usage\n\n### memoSync\n\n```ts\nimport { memoSync } from 'memofunc'\n\nconst addFn = (a: number, b: number) =\u003e a + b\n\nconst add = memoSync(add)\n\nconsole.log(add(1, 2))\n```\n\n### memoAsync\n\nIt also supports memorize async function call. After invoking once for every specified arguments, the result is located in the local memory.\n\n```ts\nimport { memoAsync } from 'memofunc'\n\nfunction sleep(time: number): Promise\u003cvoid\u003e {\n  return new Promise((res) =\u003e {\n    setTimeout(() =\u003e res(), time);\n  });\n}\n\nconst sort = memoAsync(async (arr: number[]) =\u003e {\n  // This O(1) sort only run once!\n  const res: number[] = [];\n  await Promise.all(arr.map(async (a) =\u003e {\n    await sleep(a * 1000)\n    res.push(a)\n  }))\n  return res;\n})\n\nconst arr = [3, 1, 2]\n\nconsole.log(await sort(arr))\nconsole.log(await sort(arr))\nconsole.log(await sort(arr))\n```\n\nIt also supports memorize **concurrently** async function call.\n\n```ts\nimport { memoAsync } from 'memofunc'\n\nlet count = 0;\nconst value = memoAsync(async () =\u003e {\n  // This function also only run once\n  await sleep(100);\n  return count++;\n});\n\nconst task1 = value();\nconst task2 = value();\nconst task3 = value();\n\nawait Promise.all([task1, task2, task3])\n\n// count === 1\n```\n\n### memoExternal\n\nThe caching mechanism relies on an external asynchronous service and does not store results in the local memory.\n\nUpon invoking the function, it will:\n\n1. It retrieves results from the cache. For concurrent function calls, the cache is queried only once like `memoAsync`;\n2. It either returns the cached results or calls the underlying function if the cache is empty.\n\nThis approach facilitates the development of caching solutions within distributed systems, such as Cloudflare Workers.\n\nConsider a scenario where the goal of your proxied function is to query database. Once some distributed nodes update the database, you should invalidate the related cache. This ensures that other nodes, relying entirely on the external cache service, will access the latest data available.\n\n```ts\nlet cnt = 0;\nconst func = memoExternal(async () =\u003e 0, {\n  external: {\n    async get() {\n      await sleep(100);\n      return ++cnt;\n    },\n    async set() {},\n    async clear() {\n      cnt = 0;\n    },\n    async remove() {\n      cnt = 0;\n    }\n  }\n});\n\n// It will call the external cache get function with cnt = 0\nconst tasks = await Promise.all([func(), func(), func(), func(), func()]);\nexpect(tasks).toStrictEqual([1, 1, 1, 1, 1]);\n\n// Clear the cache, cnt = 0\nfunc.clear();\n\n// It will call the external cache get function with cnt = 0\nconst tasks2 = await Promise.all([func(), func(), func(), func(), func()]);\nexpect(tasks2).toStrictEqual([1, 1, 1, 1, 1]);\n```\n\n## License\n\nMIT License © 2023 [XLor](https://github.com/yjl9903)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyjl9903%2Fmemofunc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyjl9903%2Fmemofunc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyjl9903%2Fmemofunc/lists"}