Skip to content

Commit 937171c

Browse files
committed
add AsyncStorage.setBackend to support custom backends
1 parent 8378f0f commit 937171c

File tree

2 files changed

+156
-131
lines changed

2 files changed

+156
-131
lines changed

Libraries/Storage/AsyncStorage.js

Lines changed: 143 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*/
1414
'use strict';
1515

16+
import type { AsyncStorageBackend } from './AsyncStorageTypes';
17+
1618
var NativeModules = require('NativeModules');
1719
var RCTAsyncSQLiteStorage = NativeModules.AsyncSQLiteDBStorage;
1820
var RCTAsyncRocksDBStorage = NativeModules.AsyncRocksDBStorage;
@@ -144,59 +146,6 @@ var AsyncStorage = {
144146
});
145147
},
146148

147-
/**
148-
* Merges an existing `key` value with an input value, assuming both values
149-
* are stringified JSON. Returns a `Promise` object.
150-
*
151-
* **NOTE:** This is not supported by all native implementations.
152-
*
153-
* @param key Key of the item to modify.
154-
* @param value New value to merge for the `key`.
155-
* @param callback Function that will be called with any error.
156-
* @returns A `Promise` object.
157-
*
158-
* @example <caption>Example</caption>
159-
* let UID123_object = {
160-
* name: 'Chris',
161-
* age: 30,
162-
* traits: {hair: 'brown', eyes: 'brown'},
163-
* };
164-
* // You only need to define what will be added or updated
165-
* let UID123_delta = {
166-
* age: 31,
167-
* traits: {eyes: 'blue', shoe_size: 10}
168-
* };
169-
*
170-
* AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => {
171-
* AsyncStorage.mergeItem('UID123', JSON.stringify(UID123_delta), () => {
172-
* AsyncStorage.getItem('UID123', (err, result) => {
173-
* console.log(result);
174-
* });
175-
* });
176-
* });
177-
*
178-
* // Console log result:
179-
* // => {'name':'Chris','age':31,'traits':
180-
* // {'shoe_size':10,'hair':'brown','eyes':'blue'}}
181-
*/
182-
mergeItem: function(
183-
key: string,
184-
value: string,
185-
callback?: ?(error: ?Error) => void
186-
): Promise {
187-
return new Promise((resolve, reject) => {
188-
RCTAsyncStorage.multiMerge([[key,value]], function(errors) {
189-
var errs = convertErrors(errors);
190-
callback && callback(errs && errs[0]);
191-
if (errs) {
192-
reject(errs[0]);
193-
} else {
194-
resolve(null);
195-
}
196-
});
197-
});
198-
},
199-
200149
/**
201150
* Erases *all* `AsyncStorage` for all clients, libraries, etc. You probably
202151
* don't want to call this; use `removeItem` or `multiRemove` to clear only
@@ -406,86 +355,149 @@ var AsyncStorage = {
406355
});
407356
},
408357

409-
/**
410-
* Batch operation to merge in existing and new values for a given set of
411-
* keys. This assumes that the values are stringified JSON. Returns a
412-
* `Promise` object.
413-
*
414-
* **NOTE**: This is not supported by all native implementations.
415-
*
416-
* @param keyValuePairs Array of key-value array for the items to merge.
417-
* @param callback Function that will be called with an array of any
418-
* key-specific errors found.
419-
* @returns A `Promise` object.
420-
*
421-
* @example <caption>Example</caption>
422-
* // first user, initial values
423-
* let UID234_object = {
424-
* name: 'Chris',
425-
* age: 30,
426-
* traits: {hair: 'brown', eyes: 'brown'},
427-
* };
428-
*
429-
* // first user, delta values
430-
* let UID234_delta = {
431-
* age: 31,
432-
* traits: {eyes: 'blue', shoe_size: 10},
433-
* };
434-
*
435-
* // second user, initial values
436-
* let UID345_object = {
437-
* name: 'Marge',
438-
* age: 25,
439-
* traits: {hair: 'blonde', eyes: 'blue'},
440-
* };
441-
*
442-
* // second user, delta values
443-
* let UID345_delta = {
444-
* age: 26,
445-
* traits: {eyes: 'green', shoe_size: 6},
446-
* };
447-
*
448-
* let multi_set_pairs = [['UID234', JSON.stringify(UID234_object)], ['UID345', JSON.stringify(UID345_object)]]
449-
* let multi_merge_pairs = [['UID234', JSON.stringify(UID234_delta)], ['UID345', JSON.stringify(UID345_delta)]]
450-
*
451-
* AsyncStorage.multiSet(multi_set_pairs, (err) => {
452-
* AsyncStorage.multiMerge(multi_merge_pairs, (err) => {
453-
* AsyncStorage.multiGet(['UID234','UID345'], (err, stores) => {
454-
* stores.map( (result, i, store) => {
455-
* let key = store[i][0];
456-
* let val = store[i][1];
457-
* console.log(key, val);
458-
* });
459-
* });
460-
* });
461-
* });
462-
*
463-
* // Console log results:
464-
* // => UID234 {"name":"Chris","age":31,"traits":{"shoe_size":10,"hair":"brown","eyes":"blue"}}
465-
* // => UID345 {"name":"Marge","age":26,"traits":{"shoe_size":6,"hair":"blonde","eyes":"green"}}
466-
*/
467-
multiMerge: function(
468-
keyValuePairs: Array<Array<string>>,
469-
callback?: ?(errors: ?Array<Error>) => void
470-
): Promise {
471-
return new Promise((resolve, reject) => {
472-
RCTAsyncStorage.multiMerge(keyValuePairs, function(errors) {
473-
var error = convertErrors(errors);
474-
callback && callback(error);
475-
if (error) {
476-
reject(error);
477-
} else {
478-
resolve(null);
479-
}
480-
});
481-
});
482-
},
358+
setBackend: function (
359+
backend: AsyncStorageBackend
360+
) {
361+
RCTAsyncStorage = backend;
362+
// Not all native implementations support merge.
363+
if (backend.multiMerge) {
364+
AsyncStorage.mergeItem = mergeItem;
365+
AsyncStorage.multiMerge = multiMerge;
366+
} else {
367+
delete AsyncStorage.mergeItem;
368+
delete AsyncStorage.multiMerge;
369+
}
370+
}
483371
};
484372

485-
// Not all native implementations support merge.
486-
if (!RCTAsyncStorage.multiMerge) {
487-
delete AsyncStorage.mergeItem;
488-
delete AsyncStorage.multiMerge;
373+
AsyncStorage.setBackend(RCTAsyncStorage);
374+
375+
/**
376+
* Batch operation to merge in existing and new values for a given set of
377+
* keys. This assumes that the values are stringified JSON. Returns a
378+
* `Promise` object.
379+
*
380+
* **NOTE**: This is not supported by all native implementations.
381+
*
382+
* @param keyValuePairs Array of key-value array for the items to merge.
383+
* @param callback Function that will be called with an array of any
384+
* key-specific errors found.
385+
* @returns A `Promise` object.
386+
*
387+
* @example <caption>Example</caption>
388+
* // first user, initial values
389+
* let UID234_object = {
390+
* name: 'Chris',
391+
* age: 30,
392+
* traits: {hair: 'brown', eyes: 'brown'},
393+
* };
394+
*
395+
* // first user, delta values
396+
* let UID234_delta = {
397+
* age: 31,
398+
* traits: {eyes: 'blue', shoe_size: 10},
399+
* };
400+
*
401+
* // second user, initial values
402+
* let UID345_object = {
403+
* name: 'Marge',
404+
* age: 25,
405+
* traits: {hair: 'blonde', eyes: 'blue'},
406+
* };
407+
*
408+
* // second user, delta values
409+
* let UID345_delta = {
410+
* age: 26,
411+
* traits: {eyes: 'green', shoe_size: 6},
412+
* };
413+
*
414+
* let multi_set_pairs = [['UID234', JSON.stringify(UID234_object)], ['UID345', JSON.stringify(UID345_object)]]
415+
* let multi_merge_pairs = [['UID234', JSON.stringify(UID234_delta)], ['UID345', JSON.stringify(UID345_delta)]]
416+
*
417+
* AsyncStorage.multiSet(multi_set_pairs, (err) => {
418+
* AsyncStorage.multiMerge(multi_merge_pairs, (err) => {
419+
* AsyncStorage.multiGet(['UID234','UID345'], (err, stores) => {
420+
* stores.map( (result, i, store) => {
421+
* let key = store[i][0];
422+
* let val = store[i][1];
423+
* console.log(key, val);
424+
* });
425+
* });
426+
* });
427+
* });
428+
*
429+
* // Console log results:
430+
* // => UID234 {"name":"Chris","age":31,"traits":{"shoe_size":10,"hair":"brown","eyes":"blue"}}
431+
* // => UID345 {"name":"Marge","age":26,"traits":{"shoe_size":6,"hair":"blonde","eyes":"green"}}
432+
*/
433+
function multiMerge (
434+
keyValuePairs: Array<Array<string>>,
435+
callback?: ?(errors: ?Array<Error>) => void
436+
): Promise {
437+
return new Promise((resolve, reject) => {
438+
RCTAsyncStorage.multiMerge(keyValuePairs, function(errors) {
439+
var error = convertErrors(errors);
440+
callback && callback(error);
441+
if (error) {
442+
reject(error);
443+
} else {
444+
resolve(null);
445+
}
446+
});
447+
});
448+
}
449+
450+
/**
451+
* Merges an existing `key` value with an input value, assuming both values
452+
* are stringified JSON. Returns a `Promise` object.
453+
*
454+
* **NOTE:** This is not supported by all native implementations.
455+
*
456+
* @param key Key of the item to modify.
457+
* @param value New value to merge for the `key`.
458+
* @param callback Function that will be called with any error.
459+
* @returns A `Promise` object.
460+
*
461+
* @example <caption>Example</caption>
462+
* let UID123_object = {
463+
* name: 'Chris',
464+
* age: 30,
465+
* traits: {hair: 'brown', eyes: 'brown'},
466+
* };
467+
* // You only need to define what will be added or updated
468+
* let UID123_delta = {
469+
* age: 31,
470+
* traits: {eyes: 'blue', shoe_size: 10}
471+
* };
472+
*
473+
* AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => {
474+
* AsyncStorage.mergeItem('UID123', JSON.stringify(UID123_delta), () => {
475+
* AsyncStorage.getItem('UID123', (err, result) => {
476+
* console.log(result);
477+
* });
478+
* });
479+
* });
480+
*
481+
* // Console log result:
482+
* // => {'name':'Chris','age':31,'traits':
483+
* // {'shoe_size':10,'hair':'brown','eyes':'blue'}}
484+
*/
485+
function mergeItem(
486+
key: string,
487+
value: string,
488+
callback?: ?(error: ?Error) => void
489+
): Promise {
490+
return new Promise((resolve, reject) => {
491+
RCTAsyncStorage.multiMerge([[key,value]], function(errors) {
492+
var errs = convertErrors(errors);
493+
callback && callback(errs && errs[0]);
494+
if (errs) {
495+
reject(errs[0]);
496+
} else {
497+
resolve(null);
498+
}
499+
});
500+
});
489501
}
490502

491503
function convertErrors(errs) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* @flow
3+
*/
4+
'use strict';
5+
6+
export type AsyncStorageBackend = {
7+
clear: Function,
8+
getAllKeys: Function,
9+
multiGet: Function,
10+
multiSet: Function,
11+
multiRemove: Function,
12+
multiMerge?: Function
13+
};

0 commit comments

Comments
 (0)