Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 135 additions & 56 deletions Libraries/Storage/AsyncStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* @providesModule AsyncStorage
* @noflow
* @flow-weak
* @jsdoc
*/
'use strict';

Expand All @@ -21,27 +22,58 @@ var RCTAsyncFileStorage = NativeModules.AsyncLocalStorage;
var RCTAsyncStorage = RCTAsyncRocksDBStorage || RCTAsyncSQLiteStorage || RCTAsyncFileStorage;

/**
* AsyncStorage is a simple, asynchronous, persistent, key-value storage
* @class

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why did you have to put @class here, but not in something like AlertIOS when you updated that?

* @description
* `AsyncStorage` is a simple, asynchronous, persistent, key-value storage
* system that is global to the app. 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.
* 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.
*
* On iOS, AsyncStorage is backed by native code that stores small values in a serialized
* dictionary and larger values in separate files. On Android, AsyncStorage will use either
* RocksDB or SQLite based on what is available. This JS code is a simple facade that
* provides a clear JS API, real Error objects, and simple non-multi functions. Each
* method returns a `Promise` object.
* On iOS, `AsyncStorage` is backed by native code that stores small values in a
* serialized dictionary and larger values in separate files. On Android,
* `AsyncStorage` will use either [RocksDB](http://rocksdb.org/) or SQLite
* based on what is available.
*
* The `AsyncStorage` JavaScript code is a simple facade that provides a clear
* JavaScript API, real `Error` objects, and simple non-multi functions. Each
* method in the API returns a `Promise` object.
*
* Persisting data:
* ```
* try {
* await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.');
* } catch (error) {
* // Error saving data
* }
* ```
*
* Fetching data:
* ```
* try {
* const value = await AsyncStorage.getItem('@MySuperStore:key');
* if (value !== null){
* // We have data!!
* console.log(value);
* }
* } catch (error) {
* // Error retrieving data
* }
* ```
*/
var AsyncStorage = {
_getRequests: ([]: Array<any>),
_getKeys: ([]: Array<string>),
_immediate: (null: ?number),

/**
* Fetches `key` and passes the result to `callback`, along with an `Error` if
* there is any. Returns a `Promise` object.
* Fetches an item for a `key` and invokes a callback upon completion.
* Returns a `Promise` object.
* @param key Key of the item to fetch.
* @param callback Function that will be called with a result if found or
* any error.
* @returns A `Promise` object.
*/
getItem: function(
key: string,
Expand All @@ -63,8 +95,12 @@ var AsyncStorage = {
},

/**
* Sets `value` for `key` and calls `callback` on completion, along with an
* `Error` if there is any. Returns a `Promise` object.
* Sets the value for a `key` and invokes a callback upon completion.
* Returns a `Promise` object.
* @param key Key of the item to set.
* @param value Value to set for the `key`.
* @param callback Function that will be called with any error.
* @returns A `Promise` object.
*/
setItem: function(
key: string,
Expand All @@ -85,7 +121,11 @@ var AsyncStorage = {
},

/**
* Removes an item for a `key` and invokes a callback upon completion.
* Returns a `Promise` object.
* @param key Key of the item to remove.
* @param callback Function that will be called with any error.
* @returns A `Promise` object.
*/
removeItem: function(
key: string,
Expand All @@ -105,32 +145,39 @@ var AsyncStorage = {
},

/**
* Merges existing value with input value, assuming they are stringified json.
* Returns a `Promise` object. Not supported by all native implementations.
* Merges an existing `key` value with an input value, assuming both values
* are stringified JSON. Returns a `Promise` object.
*
* Example:
* ```javascript
* **NOTE:** This is not supported by all native implementations.
*
* @param key Key of the item to modify.
* @param value New value to merge for the `key`.
* @param callback Function that will be called with any error.
* @returns A `Promise` object.
*
* @example <caption>Example</caption>
* let UID123_object = {
* name: 'Chris',
* age: 30,
* traits: {hair: 'brown', eyes: 'brown'},
* };

// need only define what will be added or updated
* // You only need to define what will be added or updated
* let UID123_delta = {
* age: 31,
* traits: {eyes: 'blue', shoe_size: 10}
* };

*
* AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => {
* AsyncStorage.mergeItem('UID123', JSON.stringify(UID123_delta), () => {
* AsyncStorage.getItem('UID123', (err, result) => {
* console.log(result);
* // => {'name':'Chris','age':31,'traits':{'shoe_size':10,'hair':'brown','eyes':'blue'}}
* });
* });
* });
* ```
*
* // Console log result:
* // => {'name':'Chris','age':31,'traits':
* // {'shoe_size':10,'hair':'brown','eyes':'blue'}}
*/
mergeItem: function(
key: string,
Expand All @@ -151,9 +198,11 @@ var AsyncStorage = {
},

/**
* 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. Returns a `Promise` object.
* Erases *all* `AsyncStorage` for all clients, libraries, etc. You probably
* don't want to call this; use `removeItem` or `multiRemove` to clear only
* your app's keys. Returns a `Promise` object.
* @param callback Function that will be called with any error.
* @returns A `Promise` object.
*/
clear: function(callback?: ?(error: ?Error) => void): Promise {
return new Promise((resolve, reject) => {
Expand All @@ -169,9 +218,12 @@ var AsyncStorage = {
},

/**
* Gets *all* keys known to the app, for all callers, libraries, etc. Returns a `Promise` object.
* Gets *all* keys known to your app; for all callers, libraries, etc.
* Returns a `Promise` object.
* @param callback Function that will be called the keys found and any error.
* @returns A `Promise` object.
*
* Example: see multiGet for example
* Example: see the `multiGet` example.
*/
getAllKeys: function(callback?: ?(error: ?Error, keys: ?Array<string>) => void): Promise {
return new Promise((resolve, reject) => {
Expand All @@ -196,7 +248,7 @@ var AsyncStorage = {
* indicate which key caused the error.
*/

/** Flushes any pending requests using a single multiget */
/** Flushes any pending requests using a single batch call to get the data. */
flushGetRequests: function(): void {
const getRequests = this._getRequests;
const getKeys = this._getKeys;
Expand Down Expand Up @@ -225,13 +277,23 @@ var AsyncStorage = {
},

/**
* multiGet invokes callback with an array of key-value pair arrays that
* matches the input format of multiSet. Returns a `Promise` object.
* This allows you to batch the fetching of items given an array of `key`
* inputs. Your callback will be invoked with an array of corresponding
* key-value pairs found:
*
* multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])
* ```
* multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])
* ```
*
* The method returns a `Promise` object.
*
* @param keys Array of key for the items to get.
* @param callback Function that will be called with a key-value array of
* the results, plus an array of any key-specific errors found.
* @returns A `Promise` object.
*
* @example <caption>Example</caption>
*
* Example:
* ```javascript
* AsyncStorage.getAllKeys((err, keys) => {
* AsyncStorage.multiGet(keys, (err, stores) => {
* stores.map((result, i, store) => {
Expand All @@ -241,7 +303,6 @@ var AsyncStorage = {
* });
* });
* });
* ```
*/
multiGet: function(
keys: Array<string>,
Expand Down Expand Up @@ -280,12 +341,20 @@ var AsyncStorage = {
},

/**
* multiSet and multiMerge take arrays of key-value array pairs that match
* the output of multiGet, e.g. Returns a `Promise` object.
* Use this as a batch operation for storing multiple key-value pairs. When
* the operation completes you'll get a single callback with any errors:
*
* multiSet([['k1', 'val1'], ['k2', 'val2']], cb);
* ```
* multiSet([['k1', 'val1'], ['k2', 'val2']], cb);
* ```
*
* The method returns a `Promise` object.
*
* Example: see multiMerge for an example
* @param keyValuePairs Array of key-value array for the items to set.
* @param callback Function that will be called with an array of any
* key-specific errors found.
* @returns A `Promise` object.
* Example: see the `multiMerge` example.
*/
multiSet: function(
keyValuePairs: Array<Array<string>>,
Expand All @@ -305,16 +374,20 @@ var AsyncStorage = {
},

/**
* Delete all the keys in the `keys` array. Returns a `Promise` object.
* Call this to batch the deletion of all keys in the `keys` array. Returns
* a `Promise` object.
*
* Example:
* ```javascript
* @param keys Array of key for the items to delete.
* @param callback Function that will be called an array of any key-specific
* errors found.
* @returns A `Promise` object.
*
* @example <caption>Example</caption>
* let keys = ['k1', 'k2'];
* AsyncStorage.multiRemove(keys, (err) => {
* // keys k1 & k2 removed, if they existed
* // do most stuff after removal (if you want)
* });
* ```
*/
multiRemove: function(
keys: Array<string>,
Expand All @@ -334,56 +407,62 @@ var AsyncStorage = {
},

/**
* Merges existing values with input values, assuming they are stringified
* json. Returns a `Promise` object.
* Batch operation to merge in existing and new values for a given set of
* keys. This assumes that the values are stringified JSON. Returns a
* `Promise` object.
*
* Not supported by all native implementations.
* **NOTE**: This is not supported by all native implementations.
*
* Example:
* ```javascript
// first user, initial values
* @param keyValuePairs Array of key-value array for the items to merge.
* @param callback Function that will be called with an array of any
* key-specific errors found.
* @returns A `Promise` object.
*
* @example <caption>Example</caption>
* // first user, initial values
* let UID234_object = {
* name: 'Chris',
* age: 30,
* traits: {hair: 'brown', eyes: 'brown'},
* };

*
* // first user, delta values
* let UID234_delta = {
* age: 31,
* traits: {eyes: 'blue', shoe_size: 10},
* };

*
* // second user, initial values
* let UID345_object = {
* name: 'Marge',
* age: 25,
* traits: {hair: 'blonde', eyes: 'blue'},
* };

*
* // second user, delta values
* let UID345_delta = {
* age: 26,
* traits: {eyes: 'green', shoe_size: 6},
* };

*
* let multi_set_pairs = [['UID234', JSON.stringify(UID234_object)], ['UID345', JSON.stringify(UID345_object)]]
* let multi_merge_pairs = [['UID234', JSON.stringify(UID234_delta)], ['UID345', JSON.stringify(UID345_delta)]]

*
* AsyncStorage.multiSet(multi_set_pairs, (err) => {
* AsyncStorage.multiMerge(multi_merge_pairs, (err) => {
* AsyncStorage.multiGet(['UID234','UID345'], (err, stores) => {
* stores.map( (result, i, store) => {
* let key = store[i][0];
* let val = store[i][1];
* console.log(key, val);
* // => UID234 {"name":"Chris","age":31,"traits":{"shoe_size":10,"hair":"brown","eyes":"blue"}}
* // => UID345 {"name":"Marge","age":26,"traits":{"shoe_size":6,"hair":"blonde","eyes":"green"}}
* });
* });
* });
* });
* ```
*
* // Console log results:
* // => UID234 {"name":"Chris","age":31,"traits":{"shoe_size":10,"hair":"brown","eyes":"blue"}}
* // => UID345 {"name":"Marge","age":26,"traits":{"shoe_size":6,"hair":"blonde","eyes":"green"}}
*/
multiMerge: function(
keyValuePairs: Array<Array<string>>,
Expand Down
2 changes: 1 addition & 1 deletion website/layout/AutodocsLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ var Method = React.createClass({
</span> || ''}
{this.props.name}
<span className="propType">
({this.props.params
({this.props.params && this.props.params.length && this.props.params

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch.

.map((param) => {
var res = param.name;
res += param.optional ? '?' : '';
Expand Down