├── .gitignore
├── API.md
├── LICENSE
├── README.md
├── example
└── nextjs
│ ├── package.json
│ └── pages
│ └── index.js
├── package.json
├── rollup.config.js
└── src
├── index.js
└── index.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # builds
7 | build
8 | dist
9 |
10 | package-lock.json
11 |
12 | /example/nextjs/node_modules
13 | /example/nextjs/.next
14 | /example/nextjs/package-lock.json
15 |
--------------------------------------------------------------------------------
/API.md:
--------------------------------------------------------------------------------
1 | # Local Async Storage API
2 |
3 | **Table of Contents**
4 |
5 | - [setItem](#setItem)
6 | - [getItem](#getItem)
7 | - [removeItem](#removeItem)
8 | - [clearStorage](#clearStorage)
9 | - [getKeys](#getKeys)
10 | - [setMultiple](#setMultiple)
11 | - [getMultiple](#getMultiple)
12 | - [removeMultiple](#removeMultiple)
13 |
14 | ## `setItem`
15 |
16 | Sets a `value` for a `key` and invokes a (optional) callback once completed.
17 |
18 | **Method**:
19 |
20 | ```js
21 | static setItem(key, value, [callback])
22 | ```
23 |
24 | **Return**:
25 |
26 | A `Promise` object.
27 |
28 | **Parameters:**
29 |
30 |
31 |
32 |
33 | NAME |
34 | TYPE |
35 | REQUIRED |
36 | DESCRIPTION |
37 |
38 |
39 |
40 |
41 | key |
42 | string |
43 | Yes |
44 | Key of the item to set. |
45 |
46 |
47 | value |
48 | string |
49 | Yes |
50 | Value to set for the key. |
51 |
52 |
53 | callback |
54 | ?(error: ?Error) => void |
55 | No |
56 | Function that will be called with any error. |
57 |
58 |
59 |
60 |
61 | **Example**:
62 |
63 | ```js
64 | setItem = async () => {
65 | try {
66 | await AsyncLocalStorage.setItem('@key', 'value')
67 | } catch(e) {
68 | // error
69 | }
70 | }
71 | ```
72 |
73 | ## `getItem`
74 |
75 | Fetches an item for a given key and invokes (optional) callback once completed.
76 |
77 | **Method**:
78 |
79 | ```js
80 | static getItem(key, [callback])
81 | ```
82 |
83 | **Return**:
84 |
85 | A `Promise` with item, if exists, `null` otherwise.
86 |
87 | **Parameters:**
88 |
89 |
90 |
91 |
92 | NAME |
93 | TYPE |
94 | REQUIRED |
95 | DESCRIPTION |
96 |
97 |
98 |
99 |
100 | key |
101 | string |
102 | Yes |
103 | Key of the item to fetch. |
104 |
105 |
106 | callback |
107 | ?(error: ?Error, result: ?string) => void |
108 | No |
109 | Function that will be called with a result if found or any error. |
110 |
111 |
112 |
113 |
114 | **Example**:
115 |
116 | ```js
117 | getItem = async () => {
118 | let value
119 |
120 | try {
121 | value = await AsyncLocalStorage.getItem('@key')
122 | } catch(e) {
123 | // error
124 | }
125 |
126 | console.log(value)
127 |
128 | /*
129 | output:
130 | value
131 | */
132 | }
133 | ```
134 |
135 | ## `removeItem`
136 |
137 | Removes an item for a `key`, and invokes (optional) callback once completed.
138 |
139 | **Method**:
140 |
141 | ```js
142 | static removeItem(key, [callback])
143 | ```
144 |
145 | **Return**:
146 |
147 | A `Promise` object.
148 |
149 | **Parameters:**
150 |
151 |
152 |
153 |
154 | NAME |
155 | TYPE |
156 | REQUIRED |
157 | DESCRIPTION |
158 |
159 |
160 |
161 |
162 | key |
163 | string |
164 | Yes |
165 | Key of the item to remove. |
166 |
167 |
168 | callback |
169 | ?(error: ?Error) => void |
170 | No |
171 | Function that will be called with any error. |
172 |
173 |
174 |
175 |
176 | **Example**:
177 |
178 | ```js
179 | removeItem = async () => {
180 | try {
181 | await AsyncLocalStorage.removeItem('@key')
182 | } catch(e) {
183 | // error
184 | }
185 | }
186 | ```
187 |
188 | ## `clearStorage`
189 |
190 | Erases all `AsyncLocalStorage` for all clients, libraries, etc. You probably don't want to call this; use [removeItem](#removeItem) or [removeMultiple](#removeMultiple) to clear only your app's keys.
191 |
192 | **Method**:
193 |
194 | ```js
195 | static clearStorage([callback])
196 | ```
197 |
198 | **Return**:
199 |
200 | A `Promise` object.
201 |
202 | **Parameters:**
203 |
204 |
205 |
206 |
207 | NAME |
208 | TYPE |
209 | REQUIRED |
210 | DESCRIPTION |
211 |
212 |
213 |
214 |
215 | callback |
216 | ?(error: ?Error) => void |
217 | No |
218 | Function that will be called with any error. |
219 |
220 |
221 |
222 |
223 | **Example**:
224 |
225 | ```js
226 | clearStorage = async () => {
227 | try {
228 | await AsyncLocalStorage.clearStorage()
229 | } catch(e) {
230 | // error
231 | }
232 | }
233 | ```
234 |
235 | ## `getKeys`
236 |
237 | Returns all keys known to your App, for all callers, libraries, etc. Once completed, invokes (optional) callback with errors (if any) and array of keys.
238 |
239 | **Method**:
240 |
241 | ```js
242 | static getKeys([callback])
243 | ```
244 |
245 | **Return**:
246 |
247 | A `Promise` object.
248 |
249 | **Parameters:**
250 |
251 |
252 |
253 |
254 | NAME |
255 | TYPE |
256 | REQUIRED |
257 | DESCRIPTION |
258 |
259 |
260 |
261 |
262 | callback |
263 | ?(error: ?Error, keys: ?Array) => void |
264 | No |
265 | Function that will be called with all keys found and any error. |
266 |
267 |
268 |
269 |
270 | **Example**:
271 |
272 | ```js
273 | getKeys = async () => {
274 | let keys = []
275 |
276 | try {
277 | keys = await AsyncLocalStorage.getKeys()
278 | } catch(e) {
279 | // error
280 | }
281 |
282 | console.log(keys)
283 |
284 | /*
285 | output:
286 | ["@key"]
287 | */
288 | }
289 | ```
290 |
291 | ## `setMultiple`
292 |
293 | Stores multiple key-value pairs in a batch. Once completed, `callback` with any errors will be called.
294 |
295 | **Method**:
296 |
297 | ```js
298 | static setMultiple(keyValuePairs, [callback])
299 | ```
300 |
301 | **Return**:
302 |
303 | A `Promise` object.
304 |
305 | **Parameters:**
306 |
307 |
308 |
309 |
310 | NAME |
311 | TYPE |
312 | REQUIRED |
313 | DESCRIPTION |
314 |
315 |
316 |
317 |
318 | keyValuePairs |
319 | Array |
320 | Yes |
321 | Array of key-value object for the items to set. |
322 |
323 |
324 | callback |
325 | ?(errors: ?Array) => void |
326 | No |
327 | Function that will be called with an array of any key-specific errors found. |
328 |
329 |
330 |
331 |
332 | **Example**:
333 |
334 | ```js
335 | setMultiple = async () => {
336 | const firstPair = { key1: 'hello1' };
337 | const secondPair = { key2: 'hello2' };
338 |
339 | try {
340 | await AsyncLocalStorage.setMultiple([value1, value2])
341 | } catch(e) {
342 | // error
343 | }
344 | }
345 | ```
346 |
347 | ## `getMultiple`
348 |
349 | Fetches multiple key-value pairs for given array of `keys` in a batch. Once completed, invokes `callback` with errors (if any) and results.
350 |
351 | **Method**:
352 |
353 | ```js
354 | static getMultiple(keys, [callback])
355 | ```
356 |
357 | **Return**:
358 |
359 | A `Promise` of array with coresponding key-value pairs found, stored as `{key: value}` array.
360 |
361 | **Parameters:**
362 |
363 |
364 |
365 |
366 | NAME |
367 | TYPE |
368 | REQUIRED |
369 | DESCRIPTION |
370 |
371 |
372 |
373 |
374 | keys |
375 | Array |
376 | Yes |
377 | Array of key for the items to get. |
378 |
379 |
380 | callback |
381 | ?(errors: ?Array, result: ?Array) => void |
382 | No |
383 | Function that will be called with a key-value array of the results, plus an array of any key-specific errors found. |
384 |
385 |
386 |
387 |
388 | **Example**:
389 |
390 | ```js
391 | getMultiple = async () => {
392 | let items
393 |
394 | try {
395 | items = await AsyncLocalStorage.getMultiple(['@key1', '@key2'])
396 | } catch(e) {
397 | // error
398 | }
399 |
400 | console.log(items)
401 |
402 | /*
403 | output:
404 | [
405 | {key1: "hello1"},
406 | {key2: "hello2"}
407 | ]
408 | */
409 | }
410 | ```
411 |
412 | ## `removeMultiple`
413 |
414 | Delete multiple key-value entries for given array of `keys` in a batch. Once completed, invokes a `callback` with errors (if any).
415 |
416 | **Method**:
417 |
418 | ```js
419 | static removeMultiple(keys, [callback])
420 | ```
421 |
422 | **Return**:
423 |
424 | A `Promise` object.
425 |
426 | **Parameters:**
427 |
428 |
429 |
430 |
431 | NAME |
432 | TYPE |
433 | REQUIRED |
434 | DESCRIPTION |
435 |
436 |
437 |
438 |
439 | keys |
440 | Array |
441 | Yes |
442 | Array of key for the items to delete. |
443 |
444 |
445 | callback |
446 | ?(errors: ?Array) => void |
447 | No |
448 | Function that will be called an array of any key-specific errors found. |
449 |
450 |
451 |
452 |
453 | **Example**:
454 |
455 | ```js
456 | removeFew = async () => {
457 | const keys = ['key1', 'key1']
458 |
459 | try {
460 | await AsyncLocalStorage.removeMultiple(keys)
461 | } catch(e) {
462 | // error
463 | }
464 | }
465 | ```
466 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2020 Create Next App
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in
8 | all copies or substantial portions of the Software.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # async-local-storage
2 |
3 | AsyncLocalStorage is an unencrypted, asynchronous, persistent, key-value storage system that is global to the app in web browser. It should be used instead of LocalStorage.
4 |
5 | [](https://www.npmjs.com/package/@createnextapp/async-local-storage) 
6 |
7 | ## ❓ Why AsyncLocalStorage instead of LocalStorage?
8 |
9 | **Cons of LocalStorage**
10 |
11 | LocalStorage is synchronous, each local storage operation you run will be one-at-a-time. For complex applications this is a big no-no as it'll slow down your app's runtime.
12 |
13 | **Pros of AsyncLocalStorage**
14 |
15 | AsyncLocalStorage is asynchronous, each local async storage operation you run will be multi-at-a-time. It'll speed up your app's runtime.
16 |
17 | The AsyncLocalStorage JavaScript code is a facade that provides [a clear JavaScript API](./API.md), real Error objects, and non-multi functions. Each method in the API returns a Promise object.
18 |
19 | ## 🔧 Install
20 |
21 | async-local-storage is available on npm. It can be installed with the following command:
22 |
23 | ```
24 | npm install --save @createnextapp/async-local-storage
25 | ```
26 |
27 | async-local-storage is available on yarn as well. It can be installed with the following command:
28 |
29 | ```
30 | yarn add @createnextapp/async-local-storage
31 | ```
32 |
33 | ## 💡 Usage
34 |
35 | To learn more how to use async-local-storage:
36 |
37 | * [API Documentation](./API.md)
38 |
39 | ### Import
40 |
41 | ```js
42 | import AsyncLocalStorage from '@createnextapp/async-local-storage'
43 | ```
44 |
45 | ### Store data
46 |
47 | ```js
48 | storeData = async () => {
49 | try {
50 | await AsyncLocalStorage.setItem('@key', 'value')
51 | } catch(e) {
52 | // error
53 | }
54 | }
55 | ```
56 |
57 | ### Read data
58 |
59 | ```js
60 | readData = async () => {
61 | let data
62 |
63 | try {
64 | data = await AsyncLocalStorage.getItem('@key')
65 | } catch(e) {
66 | // error
67 | }
68 |
69 | console.log(data)
70 |
71 | /*
72 | output:
73 | value
74 | */
75 | }
76 | ```
77 |
78 | ## 💖 Wrap Up
79 |
80 | If you think any of the `async-local-storage` can be improved, please do open a PR with any updates and submit any issues. Also, I will continue to improve this, so you might want to watch/star this repository to revisit.
81 |
82 | ## 🌟 Contribution
83 |
84 | We'd love to have your helping hand on contributions to `async-local-storage` by forking and sending a pull request!
85 |
86 | Your contributions are heartily ♡ welcome, recognized and appreciated. (✿◠‿◠)
87 |
88 | How to contribute:
89 |
90 | - Open pull request with improvements
91 | - Discuss ideas in issues
92 | - Spread the word
93 | - Reach out with any feedback
94 |
95 | ## ⚖️ License
96 |
97 | The MIT License [](https://opensource.org/licenses/MIT)
98 |
--------------------------------------------------------------------------------
/example/nextjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextjs",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "next",
8 | "build": "next build",
9 | "start": "next start"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "next": "^9.3.5",
16 | "react": "^16.13.1",
17 | "react-dom": "^16.13.1"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/example/nextjs/pages/index.js:
--------------------------------------------------------------------------------
1 | import AsyncLocalStorage from '@createnextapp/async-local-storage'
2 |
3 | export default function Index() {
4 | const setItem = async () => {
5 | try {
6 | await AsyncLocalStorage.setItem('@me', 'Bunlong')
7 | } catch (e) {
8 | // read error
9 | }
10 |
11 | console.log('Set.')
12 | }
13 |
14 | const getItem = async () => {
15 | let item
16 |
17 | try {
18 | item = await AsyncLocalStorage.getItem('@me')
19 | } catch(e) {
20 | // read error
21 | }
22 |
23 | console.log(item)
24 | }
25 |
26 | const removeItem = async () => {
27 | try {
28 | await AsyncLocalStorage.removeItem('@me')
29 | } catch(e) {
30 | // remove error
31 | }
32 |
33 | console.log('Remove.')
34 | }
35 |
36 | const clearStorage = async () => {
37 | try {
38 | await AsyncLocalStorage.clearStorage()
39 | } catch(e) {
40 | // remove error
41 | }
42 |
43 | console.log('Remove.')
44 | }
45 |
46 | const getKeys = async () => {
47 | let keys = []
48 |
49 | try {
50 | keys = await AsyncLocalStorage.getKeys()
51 | } catch(e) {
52 | // read key error
53 | }
54 |
55 | console.log(keys)
56 | }
57 |
58 | const setMultiple = async () => {
59 | const value1 = { key1: 'hello1' };
60 | const value2 = { key2: 'hello2' };
61 |
62 | try {
63 | await AsyncLocalStorage.setMultiple([value1, value2])
64 | } catch(e) {
65 | //save error
66 | }
67 |
68 | console.log("Done.")
69 | }
70 |
71 | const getMultiple = async () => {
72 | let values
73 |
74 | try {
75 | values = await AsyncLocalStorage.getMultiple(['key1', 'key2'])
76 | } catch(e) {
77 | // read error
78 | }
79 |
80 | console.log(values)
81 | }
82 |
83 | const removeMultiple = async () => {
84 | const keys = ['key1', 'key2']
85 |
86 | try {
87 | await AsyncLocalStorage.removeMultiple(keys)
88 | } catch(e) {
89 | // remove error
90 | }
91 |
92 | console.log('Done')
93 | }
94 |
95 | return (
96 | <>
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | >
106 | );
107 | }
108 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@createnextapp/async-local-storage",
3 | "version": "1.0.1",
4 | "description": "AsyncLocalStorage is an unencrypted, asynchronous, persistent, key-value storage system that is global to the app in web browser. It should be used instead of LocalStorage.",
5 | "main": "dist/async-local-storage.js",
6 | "module": "dist/async-local-storage.es.js",
7 | "jsnext:main": "dist/async-local-storage.es.js",
8 | "scripts": {
9 | "build": "rollup -c",
10 | "dev": "rollup -c -w",
11 | "test": "node test/test.js",
12 | "pretest": "npm run build"
13 | },
14 | "author": "Bunlong ",
15 | "homepage": "https://github.com/CreateNextApp/async-local-storage.git",
16 | "repository": "https://github.com/CreateNextApp/async-local-storage.git",
17 | "bugs": {
18 | "url": "https://github.com/CreateNextApp/async-local-storage/issues"
19 | },
20 | "license": "MIT",
21 | "devDependencies": {
22 | "@rollup/plugin-commonjs": "^11.1.0",
23 | "@rollup/plugin-node-resolve": "^7.1.3",
24 | "rollup": "^2.6.1",
25 | "rollup-plugin-terser": "^5.3.0"
26 | },
27 | "files": [
28 | "dist"
29 | ],
30 | "keywords": [
31 | "localstorage",
32 | "local-storage",
33 | "asyncstorage",
34 | "asynclocalstorage",
35 | "local-async-storage",
36 | "storage",
37 | "react",
38 | "reactjs",
39 | "vue",
40 | "vuejs",
41 | "angular",
42 | "angularjs",
43 | "web",
44 | "app"
45 | ]
46 | }
47 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from '@rollup/plugin-node-resolve';
2 | import commonjs from '@rollup/plugin-commonjs';
3 | import { terser } from "rollup-plugin-terser";
4 | import pkg from './package.json';
5 |
6 | export default [
7 | {
8 | input: 'src/index.js',
9 | output: [
10 | { file: pkg.main, format: 'cjs' },
11 | { file: pkg.module, format: 'es' }
12 | ],
13 | plugins: [
14 | resolve(),
15 | commonjs(),
16 | terser()
17 | ]
18 | }
19 | ];
20 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | const createPromise = (getValue, callback) => {
2 | return new Promise((resolve, reject) => {
3 | try {
4 | const value = getValue();
5 | if (callback) {
6 | callback(null, value);
7 | }
8 | resolve(value);
9 | } catch (err) {
10 | if (callback) {
11 | callback(err);
12 | }
13 | reject(err);
14 | }
15 | });
16 | };
17 |
18 | const createPromiseAll = (promises, callback, processResult) => {
19 | return Promise.all(promises).then(
20 | result => {
21 | const value = processResult ? processResult(result) : null;
22 | callback && callback(null, value);
23 | return Promise.resolve(value);
24 | },
25 | errors => {
26 | callback && callback(errors);
27 | return Promise.reject(errors);
28 | }
29 | );
30 | };
31 |
32 | export default class AsyncLocalStorage {
33 | /**
34 | * Sets value for key.
35 | */
36 | static setItem(key, value, callback) {
37 | return createPromise(() => {
38 | window.localStorage.setItem(key, value);
39 | }, callback);
40 | }
41 |
42 | /**
43 | * Fetches key value.
44 | */
45 | static getItem(key, callback) {
46 | return createPromise(() => {
47 | return window.localStorage.getItem(key);
48 | }, callback);
49 | }
50 |
51 | /**
52 | * Removes a key.
53 | */
54 | static removeItem(key, callback) {
55 | return createPromise(() => {
56 | return window.localStorage.removeItem(key);
57 | }, callback);
58 | }
59 |
60 | /**
61 | * Erases *all* AsyncLocalStorage for the domain.
62 | */
63 | static clearStorage(callback) {
64 | return createPromise(() => {
65 | window.localStorage.clear();
66 | }, callback);
67 | }
68 |
69 | /**
70 | * Gets *all* keys known to the app, for all callers, libraries, etc.
71 | */
72 | static getKeys(callback) {
73 | return createPromise(() => {
74 | const numberOfKeys = window.localStorage.length;
75 | const keys = [];
76 | for (let i = 0; i < numberOfKeys; i += 1) {
77 | const key = window.localStorage.key(i);
78 | keys.push(key);
79 | }
80 | return keys;
81 | }, callback);
82 | }
83 |
84 | /**
85 | * Takes an array of key-value json pairs.
86 | * setMultifple([{k1: 'val1'}, {k2: 'val2'}])
87 | */
88 | static setMultiple(keyValuePairs, callback) {
89 | const promises = keyValuePairs.map(item => { for(const key in item) AsyncLocalStorage.setItem(key, item[key]) });
90 | return createPromiseAll(promises, callback);
91 | }
92 |
93 | /**
94 | * getMultiple resolves to an array of key-value pair objects that matches the
95 | * input format of getMultiple.
96 | *
97 | * getMultiple(['k1', 'k2']) -> [{k1: 'val1'}, {'k2': 'val2'}]
98 | */
99 | static getMultiple(keys, callback) {
100 | const promises = keys.map(key => AsyncLocalStorage.getItem(key));
101 | const processResult = result => result.map((value, i) => {
102 | const json = {}
103 | json[keys[i]] = value
104 | return json
105 | });
106 | return createPromiseAll(promises, callback, processResult);
107 | }
108 |
109 | /**
110 | * Delete all the keys in the keys array.
111 | */
112 | static removeMultiple(keys, callback) {
113 | const promises = keys.map(key => AsyncLocalStorage.removeItem(key));
114 | return createPromiseAll(promises, callback);
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import merge from 'deep-assign';
2 |
3 | const mergeLocalStorageItem = (key, value) => {
4 | const oldValue = window.localStorage.getItem(key);
5 | const oldObject = JSON.parse(oldValue);
6 | const newObject = JSON.parse(value);
7 | const nextValue = JSON.stringify(merge({}, oldObject, newObject));
8 | window.localStorage.setItem(key, nextValue);
9 | };
10 |
11 | const createPromise = (getValue, callback): Promise<*> => {
12 | return new Promise((resolve, reject) => {
13 | try {
14 | const value = getValue();
15 | if (callback) {
16 | callback(null, value);
17 | }
18 | resolve(value);
19 | } catch (err) {
20 | if (callback) {
21 | callback(err);
22 | }
23 | reject(err);
24 | }
25 | });
26 | };
27 |
28 | const createPromiseAll = (promises, callback, processResult): Promise<*> => {
29 | return Promise.all(promises).then(
30 | result => {
31 | const value = processResult ? processResult(result) : null;
32 | callback && callback(null, value);
33 | return Promise.resolve(value);
34 | },
35 | errors => {
36 | callback && callback(errors);
37 | return Promise.reject(errors);
38 | }
39 | );
40 | };
41 |
42 | export default class AsyncLocalStorage {
43 |
44 | /**
45 | * Fetches `key` value.
46 | */
47 | static getItem(key: string, callback?: Function): Promise<*> {
48 | return createPromise(() => {
49 | return window.localStorage.getItem(key);
50 | }, callback);
51 | }
52 |
53 | /**
54 | * Sets `value` for `key`.
55 | */
56 | static setItem(key: string, value: string, callback?: Function): Promise<*> {
57 | return createPromise(() => {
58 | window.localStorage.setItem(key, value);
59 | }, callback);
60 | }
61 |
62 | /**
63 | * Removes a `key`
64 | */
65 | static removeItem(key: string, callback?: Function): Promise<*> {
66 | return createPromise(() => {
67 | return window.localStorage.removeItem(key);
68 | }, callback);
69 | }
70 |
71 | /**
72 | * Merges existing value with input value, assuming they are stringified JSON.
73 | */
74 | static mergeItem(key: string, value: string, callback?: Function): Promise<*> {
75 | return createPromise(() => {
76 | mergeLocalStorageItem(key, value);
77 | }, callback);
78 | }
79 |
80 | /**
81 | * Erases *all* AsyncLocalStorage for the domain.
82 | */
83 | static clear(callback?: Function): Promise<*> {
84 | return createPromise(() => {
85 | window.localStorage.clear();
86 | }, callback);
87 | }
88 |
89 | /**
90 | * Gets *all* keys known to the app, for all callers, libraries, etc.
91 | */
92 | static getAllKeys(callback?: Function): Promise<*> {
93 | return createPromise(() => {
94 | const numberOfKeys = window.localStorage.length;
95 | const keys = [];
96 | for (let i = 0; i < numberOfKeys; i += 1) {
97 | const key = window.localStorage.key(i);
98 | keys.push(key);
99 | }
100 | return keys;
101 | }, callback);
102 | }
103 |
104 | /**
105 | * (stub) Flushes any pending requests using a single batch call to get the data.
106 | */
107 | static flushGetRequests() {}
108 |
109 | /**
110 | * multiGet resolves to an array of key-value pair arrays that matches the
111 | * input format of multiSet.
112 | *
113 | * multiGet(['k1', 'k2']) -> [['k1', 'val1'], ['k2', 'val2']]
114 | */
115 | static multiGet(keys: Array, callback?: Function): Promise<*> {
116 | const promises = keys.map(key => AsyncLocalStorage.getItem(key));
117 | const processResult = result => result.map((value, i) => [keys[i], value]);
118 | return createPromiseAll(promises, callback, processResult);
119 | }
120 |
121 | /**
122 | * Takes an array of key-value array pairs.
123 | * multiSet([['k1', 'val1'], ['k2', 'val2']])
124 | */
125 | static multiSet(keyValuePairs: Array>, callback?: Function): Promise<*> {
126 | const promises = keyValuePairs.map(item => AsyncLocalStorage.setItem(item[0], item[1]));
127 | return createPromiseAll(promises, callback);
128 | }
129 |
130 | /**
131 | * Delete all the keys in the `keys` array.
132 | */
133 | static multiRemove(keys: Array, callback?: Function): Promise<*> {
134 | const promises = keys.map(key => AsyncLocalStorage.removeItem(key));
135 | return createPromiseAll(promises, callback);
136 | }
137 |
138 | /**
139 | * Takes an array of key-value array pairs and merges them with existing
140 | * values, assuming they are stringified JSON.
141 | *
142 | * multiMerge([['k1', 'val1'], ['k2', 'val2']])
143 | */
144 | static multiMerge(keyValuePairs: Array>, callback?: Function): Promise<*> {
145 | const promises = keyValuePairs.map(item => AsyncLocalStorage.mergeItem(item[0], item[1]));
146 | return createPromiseAll(promises, callback);
147 | }
148 | }
--------------------------------------------------------------------------------