{"id":18832267,"url":"https://github.com/tuax/tua-storage","last_synced_at":"2025-06-16T09:15:38.222Z","repository":{"id":54982742,"uuid":"115928189","full_name":"tuax/tua-storage","owner":"tuax","description":"📦 统一封装各个端（小程序、web 端、React-Native、Node 端）中对于缓存层的使用（A common storage for web(localStorage), for RN(AsyncStorage), for mini-program(wx) or just memory cache(Node.js)）","archived":false,"fork":false,"pushed_at":"2022-05-22T22:35:15.000Z","size":408,"stargazers_count":46,"open_issues_count":5,"forks_count":8,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-10T19:55:07.959Z","etag":null,"topics":["asyncstorage","javascript","localstorage","miniprogram","storage","tua","tua-storage","wx","wxapp"],"latest_commit_sha":null,"homepage":"https://tuax.github.io/tua-storage/","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/tuax.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}},"created_at":"2018-01-01T15:34:12.000Z","updated_at":"2024-03-05T08:36:05.000Z","dependencies_parsed_at":"2022-08-14T08:10:17.134Z","dependency_job_id":null,"html_url":"https://github.com/tuax/tua-storage","commit_stats":null,"previous_names":["tuateam/tua-storage"],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuax%2Ftua-storage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuax%2Ftua-storage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuax%2Ftua-storage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuax%2Ftua-storage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tuax","download_url":"https://codeload.github.com/tuax/tua-storage/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248820079,"owners_count":21166597,"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":["asyncstorage","javascript","localstorage","miniprogram","storage","tua","tua-storage","wx","wxapp"],"created_at":"2024-11-08T01:57:19.789Z","updated_at":"2025-04-14T04:23:59.531Z","avatar_url":"https://github.com/tuax.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003etua-storage\u003c/h1\u003e\n\n\u003ch4 align=\"center\"\u003e让我们构建大一统的缓存层~\u003c/h4\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://tuax.github.io/tua-storage/\"\u003e👉完整文档地址点这里👈\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://circleci.com/gh/tuateam/tua-storage/tree/master\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/circleci/project/github/tuateam/tua-storage/master.svg\" alt=\"Build Status\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://codecov.io/github/tuateam/tua-storage?branch=master\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/codecov/c/github/tuateam/tua-storage/master.svg\" alt=\"Coverage Status\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://david-dm.org/tuateam/tua-storage\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://david-dm.org/tuateam/tua-storage.svg\" alt=\"dependencies\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/tua-storage\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://badgen.net/npm/dm/tua-storage\" alt=\"Downloads per month\"\u003e\n        \u003cimg src=\"https://img.shields.io/npm/v/tua-storage.svg\" alt=\"Version\"\u003e\n        \u003cimg src=\"https://img.shields.io/npm/l/tua-storage.svg\" alt=\"License\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n## 安装\n\n```bash\n$ npm i -S tua-storage\n# OR\n$ yarn add tua-storage\n```\n\n`tua-storage` 是通过初始化时传入的 `storageEngine` 选项来区分不同的端。\n\n## 这是什么？\n`tua-storage` 是一款二次封装各个平台存储层接口，抹平各平台接口操作差异的库。采用 ES6+ 语法，将异步 api 使用 Promise 包裹，并采用 jest 进行了完整的单元测试。\n\n已适配以下场景：\n\n* web 场景：使用 `localStorage` 作为存储对象\n* 小程序场景：使用微信提供的原生存储对象\n* Node.js 场景：直接使用内存作为存储对象（其实就是使用 `object`）\n* React-Native 场景：使用 `AsyncStorage` 作为存储对象\n\n## 能干什么？\n日常开发中，在不同的平台下由于有不同的存储层接口，所以往往导致同一份代码要写几份儿。\n\n例如，小程序中保存数据要使用异步的 `wx.setStorage`、`wx.getStorage` 或对应的同步方法；而在 web 端使用 localStorage 的话，则是同步的 `setItem`、`getItem` 等方法；在 React-Native 的场景下，使用的又是 `AsyncStorage` 中异步的 `setItem`、`getItem`...\n\n然而，经过 `tua-storage` 的二次封装，以上两个方法统一变成了：\n\n* `save`\n* `load`\n\n由于异步方法没法变成同步方法，所以以上方法在所有场景下都异步返回 `Promise`。\n\n## 如何使用？\n首先参阅文档 [安装](https://tuateam.github.io/tua-storage/guide/installation.html) 将 `tua-storage` 安装到你的项目中，并正确地导入和初始化。\n\n### 常规操作\n对于存储层来说，最基本的操作自然是保存（save）、读取（load）、删除（remove，删除单个）和清除（clear，清空全部）了。\n\n```js\nimport TuaStorage from 'tua-storage'\n\nconst tuaStorage = new TuaStorage({ ... })\n\n// 返回一个 Promise\ntuaStorage.save({ key: 'foo', data: { foo: 'bar' } })\n    .then(console.log)\n    .catch(console.error)\n\n// 使用 async/await\nasync () =\u003e {\n    try {\n        const data = await tuaStorage.load({ key: 'foo' })\n        console.log(data)\n    } catch (e) {\n        console.error(e)\n    }\n}\n\ntuaStorage.remove('foo')\ntuaStorage.clear()\n```\n\n## 数据同步\n**然而，仅仅有这些我认为还不够...**\n\n想想平时我们是怎么使用存储层的\n\n* 读取一个数据\n* 正好存储层里有这个数据\n    * 返回数据（皆大欢喜，happy ending~）\n* 假如存储层里没这个数据\n    * 手动调用各种方法去同步这个数据\n    * 手动存到存储层中，以便下次读取\n\n\u003e 各位有没有看出其中麻烦的地方在哪儿？\n\n\u003e **数据同步部分的复杂度全留给了业务侧。**\n\n让我们回归这件事的【**初心**】：我仅仅需要获取这个数据！我不管它是来自存储层、来自接口数据、还是来自其他什么地方...\n\n### 数据同步函数\n因此 `tua-storage` 在读取数据时很贴心地提供了一个 `syncFn` 参数，作为数据同步的函数，当请求的数据不存在或已过期时自动调用该函数。并且数据同步后默认会保存下来，这样下次再请求时存储层中就有数据了。\n\n```js\ntuaStorage.load({\n    key: 'some data',\n    syncFn: ({ a }) =\u003e axios('some api url' + a),\n    // 以下参数会传到 syncFn 中\n    syncParams: { a: 'a' },\n})\n```\n\n这么一来，存储层就和接口层对接起来了。业务侧再也不用手动调用 api 获取数据。\n\n### 合并分散配置\n每次读取数据时如果都要手动传同步函数，实际编码时还是很麻烦...\n\n\u003e 不急，吃口药~\n\n`tua-storage` 在初始化时能够传递一个叫做 `syncFnMap` 参数。顾名思义，这是一个将 `key` 和 `syncFn` 映射起来的对象。\n\n```js\nconst tuaStorage = new TuaStorage({\n    // ...\n    syncFnMap: {\n        'data one': () =\u003e axios('data one api'),\n        'data two': () =\u003e axios('data two api'),\n        // ...\n    },\n})\n\n// 不用手动传 syncFn 了\ntuaStorage.load({ key: 'data one' })\n```\n\n### 自动生成配置\n其实手动编写每个 api 请求函数也是很繁琐的，要是有个根据配置自动生成请求函数的库就好了~\n\n诶~，巧了么不是~。各位开发者老爷们 [tua-api](https://tuateam.github.io/tua-api/) 了解一下~？\n\n`tua-storage` 搭配 `tua-api` 之后会变成这样\n\n```js\nimport TuaStorage from 'tua-storage'\n// 小程序端要引入 'tua-api/dist/mp'\nimport { getSyncFnMapByApis } from 'tua-api'\n\n// 本地写好的各种接口配置\nimport * as apis from '@/apis'\n\nconst tuaStorage = new TuaStorage({\n    syncFnMap: getSyncFnMapByApis(apis),\n})\n```\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://tuateam.github.io/tua-storage/\"\u003e👉完整文档地址点这里👈\u003c/a\u003e\n\u003c/p\u003e\n\n## License\n\n[MIT](http://opensource.org/licenses/MIT)\n\nCopyright (c) 2018-present, StEve Young\n\ninspired by [react-native-storage](https://github.com/sunnylqm/react-native-storage)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftuax%2Ftua-storage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftuax%2Ftua-storage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftuax%2Ftua-storage/lists"}