2015-03-11 19:06:03 +00:00
|
|
|
/**
|
|
|
|
* Copyright 2004-present Facebook. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* @providesModule AsyncStorage
|
|
|
|
* @flow-weak
|
|
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
|
2015-03-17 10:08:49 +00:00
|
|
|
var NativeModules = require('NativeModules');
|
2015-03-18 05:22:03 +00:00
|
|
|
var RCTAsyncLocalStorage = NativeModules.AsyncLocalStorage;
|
|
|
|
var RCTAsyncRocksDBStorage = NativeModules.AsyncRocksDBStorage;
|
2015-03-11 19:06:03 +00:00
|
|
|
|
|
|
|
// We use RocksDB if available.
|
2015-03-17 10:08:46 +00:00
|
|
|
var RCTAsyncStorage = RCTAsyncRocksDBStorage || RCTAsyncLocalStorage;
|
2015-03-11 19:06:03 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* AsyncStorage is a simple, asynchronous, persistent, global, key-value storage
|
|
|
|
* system. It should be used instead of LocalStorage.
|
|
|
|
*
|
|
|
|
* It is recommended that you use an abstraction on top of AsyncStorage instead
|
|
|
|
* of AsyncStorage directly for anything more than light usage since it
|
|
|
|
* operates globally.
|
|
|
|
*
|
|
|
|
* This JS code is a simple facad over the native iOS implementation to provide
|
|
|
|
* a clear JS API, real Error objects, and simple non-multi functions.
|
|
|
|
*/
|
|
|
|
var AsyncStorage = {
|
|
|
|
/**
|
|
|
|
* Fetches `key` and passes the result to `callback`, along with an `Error` if
|
|
|
|
* there is any.
|
|
|
|
*/
|
|
|
|
getItem: function(
|
|
|
|
key: string,
|
|
|
|
callback: (error: ?Error, result: ?string) => void
|
|
|
|
): void {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.multiGet([key], function(errors, result) {
|
2015-03-11 19:06:03 +00:00
|
|
|
// Unpack result to get value from [[key,value]]
|
|
|
|
var value = (result && result[0] && result[0][1]) ? result[0][1] : null;
|
|
|
|
callback((errors && convertError(errors[0])) || null, value);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets `value` for `key` and calls `callback` on completion, along with an
|
|
|
|
* `Error` if there is any.
|
|
|
|
*/
|
|
|
|
setItem: function(
|
|
|
|
key: string,
|
|
|
|
value: string,
|
|
|
|
callback: ?(error: ?Error) => void
|
|
|
|
): void {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.multiSet([[key,value]], function(errors) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback && callback((errors && convertError(errors[0])) || null);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
removeItem: function(
|
|
|
|
key: string,
|
|
|
|
callback: ?(error: ?Error) => void
|
|
|
|
): void {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.multiRemove([key], function(errors) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback && callback((errors && convertError(errors[0])) || null);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Merges existing value with input value, assuming they are stringified json.
|
|
|
|
*
|
|
|
|
* Not supported by all native implementations.
|
|
|
|
*/
|
|
|
|
mergeItem: function(
|
|
|
|
key: string,
|
|
|
|
value: string,
|
|
|
|
callback: ?(error: ?Error) => void
|
|
|
|
): void {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.multiMerge([[key,value]], function(errors) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback && callback((errors && convertError(errors[0])) || null);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Erases *all* AsyncStorage for all clients, libraries, etc. You probably
|
|
|
|
* don't want to call this - use removeItem or multiRemove to clear only your
|
|
|
|
* own keys instead.
|
|
|
|
*/
|
|
|
|
clear: function(callback: ?(error: ?Error) => void) {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.clear(function(error) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback && callback(convertError(error));
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets *all* keys known to the system, for all callers, libraries, etc.
|
|
|
|
*/
|
|
|
|
getAllKeys: function(callback: (error: ?Error) => void) {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.getAllKeys(function(error, keys) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback(convertError(error), keys);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The following batched functions are useful for executing a lot of
|
|
|
|
* operations at once, allowing for native optimizations and provide the
|
|
|
|
* convenience of a single callback after all operations are complete.
|
|
|
|
*
|
|
|
|
* These functions return arrays of errors, potentially one for every key.
|
|
|
|
* For key-specific errors, the Error object will have a key property to
|
|
|
|
* indicate which key caused the error.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* multiGet invokes callback with an array of key-value pair arrays that
|
|
|
|
* matches the input format of multiSet.
|
|
|
|
*
|
|
|
|
* multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])
|
|
|
|
*/
|
|
|
|
multiGet: function(
|
|
|
|
keys: Array<string>,
|
|
|
|
callback: (errors: ?Array<Error>, result: ?Array<Array<string>>) => void
|
|
|
|
): void {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.multiGet(keys, function(errors, result) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback(
|
|
|
|
(errors && errors.map((error) => convertError(error))) || null,
|
|
|
|
result
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* multiSet and multiMerge take arrays of key-value array pairs that match
|
|
|
|
* the output of multiGet, e.g.
|
|
|
|
*
|
|
|
|
* multiSet([['k1', 'val1'], ['k2', 'val2']], cb);
|
|
|
|
*/
|
|
|
|
multiSet: function(
|
|
|
|
keyValuePairs: Array<Array<string>>,
|
|
|
|
callback: ?(errors: ?Array<Error>) => void
|
|
|
|
): void {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.multiSet(keyValuePairs, function(errors) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback && callback(
|
|
|
|
(errors && errors.map((error) => convertError(error))) || null
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete all the keys in the `keys` array.
|
|
|
|
*/
|
|
|
|
multiRemove: function(
|
|
|
|
keys: Array<string>,
|
|
|
|
callback: ?(errors: ?Array<Error>) => void
|
|
|
|
): void {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.multiRemove(keys, function(errors) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback && callback(
|
|
|
|
(errors && errors.map((error) => convertError(error))) || null
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Merges existing values with input values, assuming they are stringified
|
|
|
|
* json.
|
|
|
|
*
|
|
|
|
* Not supported by all native implementations.
|
|
|
|
*/
|
|
|
|
multiMerge: function(
|
|
|
|
keyValuePairs: Array<Array<string>>,
|
|
|
|
callback: ?(errors: ?Array<Error>) => void
|
|
|
|
): void {
|
2015-03-17 10:08:46 +00:00
|
|
|
RCTAsyncStorage.multiMerge(keyValuePairs, function(errors) {
|
2015-03-11 19:06:03 +00:00
|
|
|
callback && callback(
|
|
|
|
(errors && errors.map((error) => convertError(error))) || null
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
// Not all native implementations support merge.
|
2015-03-17 10:08:46 +00:00
|
|
|
if (!RCTAsyncStorage.multiMerge) {
|
2015-03-11 19:06:03 +00:00
|
|
|
delete AsyncStorage.mergeItem;
|
|
|
|
delete AsyncStorage.multiMerge;
|
|
|
|
}
|
|
|
|
|
|
|
|
function convertError(error) {
|
|
|
|
if (!error) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
var out = new Error(error.message);
|
|
|
|
out.key = error.key; // flow doesn't like this :(
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = AsyncStorage;
|