Skip to content

Commit

Permalink
Batch AsyncStorage.multiGet calls
Browse files Browse the repository at this point in the history
Reviewed By: javache

Differential Revision: D2636553

fb-gh-sync-id: d6351b67c615d8c01c11c10e32321a9764c54c67
  • Loading branch information
milend authored and facebook-github-bot-4 committed Dec 3, 2015
1 parent 3313f76 commit a64ee7d
Showing 1 changed file with 52 additions and 9 deletions.
61 changes: 52 additions & 9 deletions Libraries/Storage/AsyncStorage.js
Expand Up @@ -33,6 +33,10 @@ var RCTAsyncStorage = RCTAsyncRocksDBStorage || RCTAsyncSQLiteStorage || RCTAsyn
* method returns a `Promise` object. * method returns a `Promise` object.
*/ */
var AsyncStorage = { var AsyncStorage = {
_getRequests: ([]: Array<any>),
_getKeys: ([]: Array<string>),
_immediate: (null: ?number),

/** /**
* Fetches `key` and passes the result to `callback`, along with an `Error` if * Fetches `key` and passes the result to `callback`, along with an `Error` if
* there is any. Returns a `Promise` object. * there is any. Returns a `Promise` object.
Expand Down Expand Up @@ -164,6 +168,32 @@ var AsyncStorage = {
* indicate which key caused the error. * indicate which key caused the error.
*/ */


/** Flushes any pending requests using a single multiget */
flushGetRequests: function(): void {
const getRequests = this._getRequests;
const getKeys = this._getKeys;

this._getRequests = [];
this._getKeys = [];

RCTAsyncStorage.multiGet(getKeys, function(errors, result) {
// Even though the runtime complexity of this is theoretically worse vs if we used a map,
// it's much, much faster in practice for the data sets we deal with (we avoid
// allocating result pair arrays). This was heavily benchmarked.
const reqLength = getRequests.length;
for (let i = 0; i < reqLength; i++) {
const request = getRequests[i];
const requestKeys = request.keys;
var requestResult = result.filter(function(resultPair) {
return requestKeys.indexOf(resultPair[0]) !== -1;
});

request.callback && request.callback(null, requestResult);
request.resolve && request.resolve(requestResult);
}
});
},

/** /**
* multiGet invokes callback with an array of key-value pair arrays that * multiGet invokes callback with an array of key-value pair arrays that
* matches the input format of multiSet. Returns a `Promise` object. * matches the input format of multiSet. Returns a `Promise` object.
Expand All @@ -174,17 +204,30 @@ var AsyncStorage = {
keys: Array<string>, keys: Array<string>,
callback?: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void callback?: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void
): Promise { ): Promise {
return new Promise((resolve, reject) => { if (!this._immediate) {
RCTAsyncStorage.multiGet(keys, function(errors, result) { this._immediate = setImmediate(() => {
var error = convertErrors(errors); this._immediate = null;
callback && callback(error, result); this.flushGetRequests();
if (error) {
reject(error);
} else {
resolve(result);
}
}); });
}

var getRequest = {
keys: keys,
callback: callback,
keyIndex: this._getKeys.length,
resolve: null,
reject: null,
};

var promiseResult = new Promise((resolve, reject) => {
getRequest.resolve = resolve;
getRequest.reject = reject;
}); });

this._getRequests.push(getRequest);
this._getKeys.push.apply(this._getKeys, keys);

return promiseResult;
}, },


/** /**
Expand Down

0 comments on commit a64ee7d

Please sign in to comment.