local storage wrapper for both react-native and browser. Support size controlling, auto expiring, remote data auto syncing and getting batch data in one query.

Overview

react-native-storage Backers on Open Collective Sponsors on Open Collective Build Status npm version

This is a local storage wrapper for both react native apps (using AsyncStorage) and web apps (using localStorage). ES6 syntax, promise for async load, fully tested with jest.

查看中文文档请点击 README-CHN.md

Install

npm install react-native-storage
npm install @react-native-community/async-storage

or

yarn add react-native-storage
yarn add @react-native-community/async-storage

Link

react-native link @react-native-community/async-storage

Usage

Init

import Storage from 'react-native-storage';
import AsyncStorage from '@react-native-community/async-storage';

const storage = new Storage({
  // maximum capacity, default 1000 key-ids
  size: 1000,

  // Use AsyncStorage for RN apps, or window.localStorage for web apps.
  // If storageBackend is not set, data will be lost after reload.
  storageBackend: AsyncStorage, // for web: window.localStorage

  // expire time, default: 1 day (1000 * 3600 * 24 milliseconds).
  // can be null, which means never expire.
  defaultExpires: 1000 * 3600 * 24,

  // cache data in the memory. default is true.
  enableCache: true,

  // if data was not found in storage or expired data was found,
  // the corresponding sync method will be invoked returning
  // the latest data.
  sync: {
    // we'll talk about the details later.
  }
});

export default storage;

Save & Load & Remove

// Save something with key only. (using only a keyname but no id)
// This key should be unique. This is for data frequently used.
// The key and value pair is permanently stored unless you remove it yourself.
storage.save({
  key: 'loginState', // Note: Do not use underscore("_") in key!
  data: {
    from: 'some other site',
    userid: 'some userid',
    token: 'some token'
  },

  // if expires not specified, the defaultExpires will be applied instead.
  // if set to null, then it will never expire.
  expires: 1000 * 3600
});

// load
storage
  .load({
    key: 'loginState',

    // autoSync (default: true) means if data is not found or has expired,
    // then invoke the corresponding sync method
    autoSync: true,

    // syncInBackground (default: true) means if data expired,
    // return the outdated data first while invoking the sync method.
    // If syncInBackground is set to false, and there is expired data,
    // it will wait for the new data and return only after the sync completed.
    // (This, of course, is slower)
    syncInBackground: true,

    // you can pass extra params to the sync method
    // see sync example below
    syncParams: {
      extraFetchOptions: {
        // blahblah
      },
      someFlag: true
    }
  })
  .then(ret => {
    // found data go to then()
    console.log(ret.userid);
  })
  .catch(err => {
    // any exception including data not found
    // goes to catch()
    console.warn(err.message);
    switch (err.name) {
      case 'NotFoundError':
        // TODO;
        break;
      case 'ExpiredError':
        // TODO
        break;
    }
  });

// --------------------------------------------------

// Save something with key and id.
// "key-id" data size cannot surpass the size parameter you pass in the constructor.
// By default the 1001st data will overwrite the 1st data item.
// If you then load the 1st data, a catch(NotFoundError) or sync will be invoked.
var userA = {
  name: 'A',
  age: 20,
  tags: ['geek', 'nerd', 'otaku']
};

storage.save({
  key: 'user', // Note: Do not use underscore("_") in key!
  id: '1001', // Note: Do not use underscore("_") in id!
  data: userA,
  expires: 1000 * 60
});

// load
storage
  .load({
    key: 'user',
    id: '1001'
  })
  .then(ret => {
    // found data goes to then()
    console.log(ret.userid);
  })
  .catch(err => {
    // any exception including data not found
    // goes to catch()
    console.warn(err.message);
    switch (err.name) {
      case 'NotFoundError':
        // TODO;
        break;
      case 'ExpiredError':
        // TODO
        break;
    }
  });

// --------------------------------------------------

// get all ids for "key-id" data under a key,
// note: does not include "key-only" information (which has no ids)
storage.getIdsForKey('user').then(ids => {
  console.log(ids);
});

// get all the "key-id" data under a key
// !! important: this does not include "key-only" data
storage.getAllDataForKey('user').then(users => {
  console.log(users);
});

// clear all "key-id" data under a key
// !! important: "key-only" data is not cleared by this function
storage.clearMapForKey('user');

// --------------------------------------------------

// remove a single record
storage.remove({
  key: 'lastPage'
});
storage.remove({
  key: 'user',
  id: '1001'
});

// clear map and remove all "key-id" data
// !! important: "key-only" data is not cleared, and is left intact
storage.clearMap();

Sync remote data(refresh)

There are two ways to set the sync method. You can pass the sync method in the constructor's parameter, as a function in an object, or you can define it at any time as shown below:

storage.sync = {
  // The name of the sync method must be the same as the data's key name
  // And the passed params will be an all-in-one object.
  // You can return a value or a promise here
  async user(params) {
    let {
      id,
      syncParams: { extraFetchOptions, someFlag }
    } = params;
    const response = await fetch('user/?id=' + id, {
      ...extraFetchOptions
    });
    const responseText = await response.text();
    console.log(`user${id} sync resp: `, responseText);
    const json = JSON.parse(responseText);
    if (json && json.user) {
      storage.save({
        key: 'user',
        id,
        data: json.user
      });
      if (someFlag) {
        // do something for some custom flag
      }
      // return required data when succeed
      return json.user;
    } else {
      // throw error when failed
      throw new Error(`error syncing user${id}`));
    }
  }
};

In the following example the sync method is called, when you invoke storage.load:

storage.load({
	key: 'user',
	id: '1002'
}).then(...)

If there is no user 1002 currently in storage, then storage.sync.user will be invoked to fetch and return the remote data.

Load batch data

// Load batch data with an array of `storage.load` parameters.
// It will invoke each key's sync method,
// and when all are complete will return all the data in an ordered array.
// The sync methods behave according to the syncInBackground setting: (default true)
// When set to true (the default), if timed out will return the current value
// while when set to false, will wait till the sync method completes

storage.getBatchData([
	{ key: 'loginState' },
	{ key: 'checkPoint', syncInBackground: false },
	{ key: 'balance' },
	{ key: 'user', id: '1009' }
])
.then(results => {
	results.forEach(result => {
		console.log(result);
	})
})

// Load batch data with one key and an array of ids.
storage.getBatchDataWithIds({
	key: 'user',
	ids: ['1001', '1002', '1003']
})
.then( ... )

There is an important difference between the way these two methods perform: getBatchData will invoke separate sync methods for each different key one after the other when the corresponding data is missing or not in sync. However, getBatchDataWithIds will collect a list of the missing data, pushing their ids to an array, and then pass the array to the single corresponding sync method once, reducing the number of requests, so you need to implement array query on the server side and handle the parameters of sync method properly. Note that the id parameter can be a single string or an array of strings.

You are welcome to ask any question in the issues page.

Contributors

This project exists thanks to all the people who contribute. [Contribute].

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Comments
  • 怎么才能取出异步存的值,然后把它给header呢

    怎么才能取出异步存的值,然后把它给header呢

    想实现这样的操作,但是一直拿不到存到缓存里面的token

    instance.interceptors.request.use(
        config => {
            //config.headers['blade-auth'] = 'bearer ' + data;
            storage.load({
                key: 'token',
            }).then((data) => {
                config.headers['blade-auth'] = 'bearer ' + data;
                console.log('新版的操作', data);
                return config;
    
            })
        },
        error => {
            // do something with request error
            console.log('error1:' + error); // for debug
            return Promise.reject(error);
        },
    );
    
    opened by Zhongxiangyun 18
  • 将storage放到全局是不是需要react-native某个版本以上才行啊?

    将storage放到全局是不是需要react-native某个版本以上才行啊?

    你好,我使用 global.storage = storage; 将storage放在全局, 之后在其它地方直接使用 storage.save({ key: 'loginInfo', rawData: obj, }); 提示找不到storage这个变量,我想问一下是不是需要在使用的地方在import一下啊?如果这样的话,global这个还有什么用?

    opened by phonebird 15
  • Way to remove cache?

    Way to remove cache?

    I've set enableCache: true and this is causing few issues in the app.

    When the user is logged out, I'm removing all the user data with the below code:

    storage.remove({
      key: 'user'
    });
    

    But the problem is If I immediately sign in with a new user account, The old user account data is loaded due to enableCache: true.

    When I set enableCache: false everything works fine.

    So, I'm wondering if there is an option to manually expire cache when a user does log out.

    opened by abhionlyone 14
  • 写了一个Storage.JS

    写了一个Storage.JS

    import { AsyncStorage } from 'react-native';
    import Storage from 'react-native-storage';
    
    var storage = new Storage({
        // 最大容量,默认值1000条数据循环存储
        size: 1000,
    
        // 存储引擎:对于RN使用AsyncStorage,对于web使用window.localStorage
        // 如果不指定则数据只会保存在内存中,重启后即丢失
        storageBackend: AsyncStorage,
    
        // 数据过期时间,默认一整天(1000 * 3600 * 24 毫秒),设为null则永不过期
        defaultExpires: 1000 * 3600 * 24,
    
        // 读写时在内存中缓存数据。默认启用。
        enableCache: true,
    
        // 如果storage中没有相应数据,或数据已过期,
        // 则会调用相应的sync方法,无缝返回最新数据。
        // sync方法的具体说明会在后文提到
        // 你可以在构造函数这里就写好sync的方法
        // 或是写到另一个文件里,这里require引入
        // 或是在任何时候,直接对storage.sync进行赋值修改
        sync: require('./sync')
    })
    
    global.storage = storage;
    

    在别的地方引用,出现ReferenceError: storage is not defined,在入口引用该JS直接报错,请问是什么原因

    opened by Rcrosp 13
  • WEB上使用时webpack打包报错

    WEB上使用时webpack打包报错

    是按照文档配置的,可是依然报错 error in ./~/react-native-storage/storage.js module parse failed: ~\node_modules\react-native-storage\storage.js unexpected token (188:39) you may need an appropriate loader to handle this file type. 整个项目都是用es6写的就这个报错

    opened by mapleafgo 13
  • Does it support reactjs?

    Does it support reactjs?

    I have a project with shared codebase for native and web. On react-native it runs with no problem, but when I try to run on reactjs I get error.

    react-native-storage/storage.js Unexpected token (186:39) You may need an appropriate loader to handle this file type.

    opened by jaynakus 13
  • 为什么 storage.load() 出来的结果都是 undefined

    为什么 storage.load() 出来的结果都是 undefined

    求助@sunnylqm storage.save()没有抛异常,但是我调用storage.load()得到的结果都是undefined,我使用的版本是0.1.4。下面是我测试的一段代码:

    storage.save({
                key: "name",
                rowData: {
                    firstName: "tang",
                    name: "henry"
                }
            }).then(() => {
                storage.load({
                    key: "name"
                }).then(ret => {
                    console.log("ret:" + ret);
                }).catch(error => {
                    console.log("load error:" + error);
                })
            }).catch(error => {
                console.log("save error:" + error);
            });
    
    opened by henr 12
  • 安卓机上load无法使用的问题

    安卓机上load无法使用的问题

    系统:MIUI8

    代码如下: storage.js

    import Storage from 'react-native-storage'
    import { AsyncStorage } from 'react-native';
    
    
    var storage = new Storage({
        size: 1000,
        storageBackend: AsyncStorage,
        defaultExpires: null,
    	enableCache: true,
    	sync : {
    		
    	}
    })
    global.storage = storage;
    
    

    index.js

    import { AppRegistry } from 'react-native';
    import './app/util/storage'
    ...
    

    使用的地方:

    async function checkTokenExp() {
        var expTime = 0
        var token = ''
        var now = Date.parse(new Date()) / 1000
        console.log(now)
        await storage.load({'key': 'tokenExp'}).then(ret => {
            console.log(ret)
            token = ret
            var base64 = new Base64()
            var tokenInfoArr = token.split('.')
            let exp = base64.decode(tokenInfoArr[1])
            exp = exp.split('}')
            exp = exp[0] + '}'
            expTime = JSON.parse(exp).exp
        }).catch(err => {
            console.log(err)
        })
    }
    

    在iOS设备上面能够运行then里面的代码并打印出nowret,但是在android设备上面只能打印出now,没有打印ret也没有打印err

    在iOS和android上使用方法不一样?

    opened by ssshen 11
  • react-native环境,导入后初始化,之后打印storage,没有找到相关方法

    react-native环境,导入后初始化,之后打印storage,没有找到相关方法

    `var storage = new Storage({

    size: 10000,

    //数据过期时间,默认一年(1000 * 3600 * 24 * 365 秒) defaultExpires: 1000 * 3600 * 24 * 365,

    //读写时在内存中缓存数据。默认启用。 enableCache: true,

    sync : { //同步方法的具体说明会在后文提到 } });

    console.log(storage);`

    _SIZE:10000 _innerVersion:10 _m:Object _mapPromise:Promise _s:Object cache:Object defaultExpires:31536000000 enableCache:true isPromise:true sync:Object

    以上是log的输出,并没有save、load等方法可用,请问我是使用有问题吗?谢谢……

    opened by wanchun0222 10
  • 使用getAllDataForKey方法查询某个key下的所有数据会报错

    使用getAllDataForKey方法查询某个key下的所有数据会报错

    我设置的是key都相同id不同 # 使用getAllDataForKey方法查询某个key下的所有数据会报下面这个错,查询都有问题 YellowBox.js:71 Possible Unhandled Promise Rejection (id: 0): ExpiredError { "message": "Expired! Params: 此处后面是本地存储的数据

    # 用load方法查报如下错 Not Found! Params:

    查某个key下的所有id没问题 // 获取某个key下的所有id storage.getIdsForKey('user').then(ids => { console.log(ids); });

    // 获取某个key下的所有数据 storage.getAllDataForKey('user').then(users => { console.log(users); });

    opened by IrenaChou 9
  • 一个实例化的Stroage是否能够存储多个带有不同key值的数据?如何能够save多个带有不同key值的数据?

    一个实例化的Stroage是否能够存储多个带有不同key值的数据?如何能够save多个带有不同key值的数据?

    一个实例化的Stroage是否能够存储多个带有不同key值的数据?如何能够save多个带有不同key值的数据?

    例如:

           storage.save({
              key: 'data1',
              rawData: data1,
              expires: null,
            });
            storage.save({
              key: 'data2',
              rawData: data2,
              expires: null,
            })
    
    opened by pampang 9
  • Vulnerabilities during npm install

    Vulnerabilities during npm install

    Lots of vulnerabilities are reported while doing npm i. Also cant fix all of them with npm audit fix. This leads to security concerns on this package. Can somebody pls fix this?

    opened by koustubh-desai 0
  •  database or disk is full

    database or disk is full

    problem

    Possible Unhandled Promise Rejection (id: 0): Error: database or disk is full (code 13 SQLITE_FULL)

    description

    I saved an image with the data format base64

    opened by 814704261 1
  • Bundle size doubled in 1.0.1?

    Bundle size doubled in 1.0.1?

    Hello,

    According to bundlephobia, the package almost doubled in size from 1.0.0 to 1.0.1. In the changelog it just looks like two bug fixes.

    Just curious if you know what the reason is for this. Thanks.

    opened by Dilan1020 1
  • "data" is required in save()

    -----storage.js----- import Storage from 'react-native-storage'; import AsyncStorage from '@react-native-community/async-storage';

    const storage = new Storage({ // 最大容量,默认值1000条数据循环存储 size: 1000,

    // 存储引擎:对于RN使用AsyncStorage,对于web使用window.localStorage // 如果不指定则数据只会保存在内存中,重启后即丢失 storageBackend: AsyncStorage,

    // 数据过期时间,默认一整天(1000 * 3600 * 24 毫秒),设为null则永不过期 defaultExpires: null,

    // 读写时在内存中缓存数据。默认启用。 enableCache: true, // 你可以在构造函数这里就写好sync的方法 // 或是在任何时候,直接对storage.sync进行赋值修改 // 或是写到另一个文件里,这里require引入

    // 如果storage中没有相应数据,或数据已过期, // 则会调用相应的sync方法,无缝返回最新数据。 // sync方法的具体说明会在后文提到 // sync: require('你可以另外写一个文件专门处理sync'), }); global.storage = storage;

    --------App.js-------------- import storage from './src/util/storage';

    --------***.js------------- storage.save({ key: 'user', // 注意:请不要在key中使用_下划线符号! id: '1001', // 注意:请不要在id中使用_下划线符号! data: '111111', expires: 1000 * 60, }); 调用key-id保存方法时保存,报错信息: [Fri Jul 24 2020 15:14:28.988] ERROR Please do not use "_" in key! [Fri Jul 24 2020 15:14:29.800] ERROR "data" is required in save()! [Fri Jul 24 2020 15:14:29.200] ERROR "data" is required in save()!

    opened by GlimmerExands 3
  • Please do not use

    Please do not use "_" in key!"data" is required in save()!

    -----storage.js----- import Storage from 'react-native-storage'; import AsyncStorage from '@react-native-community/async-storage';

    const storage = new Storage({ // 最大容量,默认值1000条数据循环存储 size: 1000,

    // 存储引擎:对于RN使用AsyncStorage,对于web使用window.localStorage // 如果不指定则数据只会保存在内存中,重启后即丢失 storageBackend: AsyncStorage,

    // 数据过期时间,默认一整天(1000 * 3600 * 24 毫秒),设为null则永不过期 defaultExpires: null,

    // 读写时在内存中缓存数据。默认启用。 enableCache: true, // 你可以在构造函数这里就写好sync的方法 // 或是在任何时候,直接对storage.sync进行赋值修改 // 或是写到另一个文件里,这里require引入

    // 如果storage中没有相应数据,或数据已过期, // 则会调用相应的sync方法,无缝返回最新数据。 // sync方法的具体说明会在后文提到 // sync: require('你可以另外写一个文件专门处理sync'), }); global.storage = storage;

    --------App.js-------------- import storage from './src/util/storage';

    --------***.js------------- storage.save({ key: 'user', // 注意:请不要在key中使用_下划线符号! id: '1001', // 注意:请不要在id中使用_下划线符号! data: '111111', expires: 1000 * 60, }); 调用key-id保存方法时保存,报错信息: [Fri Jul 24 2020 15:14:28.988] ERROR Please do not use "_" in key! [Fri Jul 24 2020 15:14:29.800] ERROR "data" is required in save()! [Fri Jul 24 2020 15:14:29.200] ERROR "data" is required in save()!

    opened by GlimmerExands 0
Owner
Sunny Luo
A typo fixer
Sunny Luo
A lightweight vanilla ES6 cookies and local storage JavaScript library

?? CrumbsJS ?? A lightweight, intuitive, vanilla ES6 fueled JS cookie and local storage library. Quick Start Adding a single cookie or a local storage

null 233 Dec 13, 2022
Cross domain local storage, with permissions

Cross domain local storage, with permissions. Enables multiple browser windows/tabs, across a variety of domains, to share a single localStorage. Feat

Zendesk 2.2k Jan 6, 2023
An AngularJS module that gives you access to the browsers local storage with cookie fallback

angular-local-storage An Angular module that gives you access to the browsers local storage Table of contents: Get Started Video Tutorial Development

Gregory Pike 2.9k Dec 25, 2022
Browser storage interface for IndexedDB, WebSQL, LocalStorage, and in memory data with Schema and data validator.

Client Web Storage Browser storage interface for IndexedDB, WebSQL, LocalStorage, and in memory data with basic Schema and data validation. Installati

Before Semicolon 19 Sep 30, 2022
Cross-browser storage for all use cases, used across the web.

Store.js Cross-browser storage for all use cases, used across the web. Store.js has been around since 2010 (first commit, v1 release). It is used in p

Marcus Westin 13.9k Dec 29, 2022
Store your data in the world's fastest and most secure storage, powered by the blockchain technology⚡️

Store your data in the world's fastest and most secure storage, powered by the blockchain technology.

BlockDB 3 Mar 5, 2022
Expirable data storage based on localStorage and sessionStorage.

Expirable storage About The Project Expirable data storage based on localStorage and sessionStorage. Getting Started To get a local copy up and runnin

Wayfair Tech – Incubator 5 Oct 31, 2022
The perfect combination: local business shopping and crypto.

The perfect combination: local business shopping and crypto. Get passive income and support local businesses.

Mauricio Figueiredo 4 Mar 19, 2022
A javascript based module to access and perform operations on Linode object storage via code.

Linode Object Storage JS Module A javascript based module to access and perform operations on Linode object storage via code. Code Guardian Installing

Core.ai 3 Jan 11, 2022
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.

localForage localForage is a fast and simple storage library for JavaScript. localForage improves the offline experience of your web app by using asyn

localForage 21.5k Jan 4, 2023
JS / CSS / files loader + key/value storage

bag.js - JS / CSS loader + KV storage bag.js is loader for .js / .css and other files, that uses IndexedDB/ WebSQL / localStorage for caching. Conside

Nodeca 86 Nov 28, 2022
:sunglasses: Everything you need to know about Client-side Storage.

awesome-web-storage Everything you need to know about Client-side Storage. Table of Contents Introduction Browser Support Cookies Pros Cons API Useful

Varun Malhotra 420 Dec 12, 2022
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.

localForage localForage is a fast and simple storage library for JavaScript. localForage improves the offline experience of your web app by using asyn

localForage 21.5k Jan 1, 2023
⁂ The simple file storage service for IPFS & Filecoin

⁂ web3.storage The simple file storage service for IPFS & Filecoin. Getting started This project uses node v16 and npm v7. It's a monorepo that use np

Web3 Storage 423 Dec 25, 2022
This is an upload script which allows you to upload to web3 storage using JS.

This is an upload script which allows you to upload to web3 storage using JS. first make sure to run npm install on the directory run script using nod

null 1 Dec 24, 2021
Dustbin - Just Another Text Storage Service

Dustbin It's just another text storage service built in fastify. API Ofcouse we

Dustbin Server 25 Dec 3, 2022
db.js is a wrapper for IndexedDB to make it easier to work against

db.js db.js is a wrapper for IndexedDB to make it easier to work against, making it look more like a queryable API. Usage Add a reference to db.js in

Aaron Powell 790 Nov 28, 2022
jStorage is a simple key/value database to store data on browser side

NB! This project is in a frozen state. No more API changes. Pull requests for bug fixes are welcomed, anything else gets most probably ignored. A bug

Andris Reinman 1.5k Dec 10, 2022
Vue.js localStorage plugin with types support

VueLocalStorage LocalStorage plugin inspired by Vue typed props which take a care of typecasting for Vue.js 1 and 2 with SSR support. Install npm inst

Alexander Avakov 669 Nov 29, 2022