Skip to content

Commit a64ee7d

Browse files
milendfacebook-github-bot-4
authored and
facebook-github-bot-4
committed
Batch AsyncStorage.multiGet calls
Reviewed By: javache Differential Revision: D2636553 fb-gh-sync-id: d6351b67c615d8c01c11c10e32321a9764c54c67
1 parent 3313f76 commit a64ee7d

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

Libraries/Storage/AsyncStorage.js

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ var RCTAsyncStorage = RCTAsyncRocksDBStorage || RCTAsyncSQLiteStorage || RCTAsyn
3333
* method returns a `Promise` object.
3434
*/
3535
var AsyncStorage = {
36+
_getRequests: ([]: Array<any>),
37+
_getKeys: ([]: Array<string>),
38+
_immediate: (null: ?number),
39+
3640
/**
3741
* Fetches `key` and passes the result to `callback`, along with an `Error` if
3842
* there is any. Returns a `Promise` object.
@@ -164,6 +168,32 @@ var AsyncStorage = {
164168
* indicate which key caused the error.
165169
*/
166170

171+
/** Flushes any pending requests using a single multiget */
172+
flushGetRequests: function(): void {
173+
const getRequests = this._getRequests;
174+
const getKeys = this._getKeys;
175+
176+
this._getRequests = [];
177+
this._getKeys = [];
178+
179+
RCTAsyncStorage.multiGet(getKeys, function(errors, result) {
180+
// Even though the runtime complexity of this is theoretically worse vs if we used a map,
181+
// it's much, much faster in practice for the data sets we deal with (we avoid
182+
// allocating result pair arrays). This was heavily benchmarked.
183+
const reqLength = getRequests.length;
184+
for (let i = 0; i < reqLength; i++) {
185+
const request = getRequests[i];
186+
const requestKeys = request.keys;
187+
var requestResult = result.filter(function(resultPair) {
188+
return requestKeys.indexOf(resultPair[0]) !== -1;
189+
});
190+
191+
request.callback && request.callback(null, requestResult);
192+
request.resolve && request.resolve(requestResult);
193+
}
194+
});
195+
},
196+
167197
/**
168198
* multiGet invokes callback with an array of key-value pair arrays that
169199
* matches the input format of multiSet. Returns a `Promise` object.
@@ -174,17 +204,30 @@ var AsyncStorage = {
174204
keys: Array<string>,
175205
callback?: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void
176206
): Promise {
177-
return new Promise((resolve, reject) => {
178-
RCTAsyncStorage.multiGet(keys, function(errors, result) {
179-
var error = convertErrors(errors);
180-
callback && callback(error, result);
181-
if (error) {
182-
reject(error);
183-
} else {
184-
resolve(result);
185-
}
207+
if (!this._immediate) {
208+
this._immediate = setImmediate(() => {
209+
this._immediate = null;
210+
this.flushGetRequests();
186211
});
212+
}
213+
214+
var getRequest = {
215+
keys: keys,
216+
callback: callback,
217+
keyIndex: this._getKeys.length,
218+
resolve: null,
219+
reject: null,
220+
};
221+
222+
var promiseResult = new Promise((resolve, reject) => {
223+
getRequest.resolve = resolve;
224+
getRequest.reject = reject;
187225
});
226+
227+
this._getRequests.push(getRequest);
228+
this._getKeys.push.apply(this._getKeys, keys);
229+
230+
return promiseResult;
188231
},
189232

190233
/**

0 commit comments

Comments
 (0)