UNPKG

@react-native-async-storage/async-storage

Version:

Asynchronous, persistent, key-value storage system for React Native.

358 lines (315 loc) 12.5 kB
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import { checkValidArgs, checkValidInput, convertError, convertErrors } from './helpers'; import RCTAsyncStorage from './RCTAsyncStorage'; if (!RCTAsyncStorage) { throw new Error(`[@RNC/AsyncStorage]: NativeModule: AsyncStorage is null. To fix this issue try these steps: • Rebuild and restart the app. • Run the packager with \`--reset-cache\` flag. • If you are using CocoaPods on iOS, run \`pod install\` in the \`ios\` directory and then rebuild and re-run the app. • If this happens while testing with Jest, check out docs how to integrate AsyncStorage with it: https://react-native-async-storage.github.io/async-storage/docs/advanced/jest If none of these fix the issue, please open an issue on the Github repository: https://github.com/react-native-async-storage/async-storage/issues `); } /** * `AsyncStorage` is a simple, unencrypted, asynchronous, persistent, key-value * storage system that is global to the app. It should be used instead of * LocalStorage. * * See https://react-native-async-storage.github.io/async-storage/docs/api */ const AsyncStorage = (() => { let _getRequests = []; let _getKeys = []; let _immediate = null; return { /** * Fetches an item for a `key` and invokes a callback upon completion. * * See https://react-native-async-storage.github.io/async-storage/docs/api#getitem */ getItem: (key, callback) => { return new Promise((resolve, reject) => { checkValidInput(key); RCTAsyncStorage.multiGet([key], (errors, result) => { var _result$; // Unpack result to get value from [[key,value]] const value = result !== null && result !== void 0 && (_result$ = result[0]) !== null && _result$ !== void 0 && _result$[1] ? result[0][1] : null; const errs = convertErrors(errors); callback === null || callback === void 0 ? void 0 : callback(errs === null || errs === void 0 ? void 0 : errs[0], value); if (errs) { reject(errs[0]); } else { resolve(value); } }); }); }, /** * Sets the value for a `key` and invokes a callback upon completion. * * See https://react-native-async-storage.github.io/async-storage/docs/api#setitem */ setItem: (key, value, callback) => { return new Promise((resolve, reject) => { checkValidInput(key, value); RCTAsyncStorage.multiSet([[key, value]], errors => { const errs = convertErrors(errors); callback === null || callback === void 0 ? void 0 : callback(errs === null || errs === void 0 ? void 0 : errs[0]); if (errs) { reject(errs[0]); } else { resolve(); } }); }); }, /** * Removes an item for a `key` and invokes a callback upon completion. * * See https://react-native-async-storage.github.io/async-storage/docs/api#removeitem */ removeItem: (key, callback) => { return new Promise((resolve, reject) => { checkValidInput(key); RCTAsyncStorage.multiRemove([key], errors => { const errs = convertErrors(errors); callback === null || callback === void 0 ? void 0 : callback(errs === null || errs === void 0 ? void 0 : errs[0]); if (errs) { reject(errs[0]); } else { resolve(); } }); }); }, /** * Merges an existing `key` value with an input value, assuming both values * are stringified JSON. * * **NOTE:** This is not supported by all native implementations. * * See https://react-native-async-storage.github.io/async-storage/docs/api#mergeitem */ mergeItem: (key, value, callback) => { return new Promise((resolve, reject) => { checkValidInput(key, value); RCTAsyncStorage.multiMerge([[key, value]], errors => { const errs = convertErrors(errors); callback === null || callback === void 0 ? void 0 : callback(errs === null || errs === void 0 ? void 0 : errs[0]); if (errs) { reject(errs[0]); } else { resolve(); } }); }); }, /** * 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. * * See https://react-native-async-storage.github.io/async-storage/docs/api#clear */ clear: callback => { return new Promise((resolve, reject) => { RCTAsyncStorage.clear(error => { const err = convertError(error); callback === null || callback === void 0 ? void 0 : callback(err); if (err) { reject(err); } else { resolve(); } }); }); }, /** * Gets *all* keys known to your app; for all callers, libraries, etc. * * See https://react-native-async-storage.github.io/async-storage/docs/api#getallkeys */ getAllKeys: callback => { return new Promise((resolve, reject) => { RCTAsyncStorage.getAllKeys((error, keys) => { const err = convertError(error); callback === null || callback === void 0 ? void 0 : callback(err, keys); if (keys) { resolve(keys); } else { reject(err); } }); }); }, /** * 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. */ /** * Flushes any pending requests using a single batch call to get the data. * * See https://react-native-async-storage.github.io/async-storage/docs/api#flushgetrequests * */ flushGetRequests: () => { const getRequests = _getRequests; const getKeys = _getKeys; _getRequests = []; _getKeys = []; RCTAsyncStorage.multiGet(getKeys, (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. // // Is there a way to avoid using the map but fix the bug in this breaking test? // https://github.com/facebook/react-native/commit/8dd8ad76579d7feef34c014d387bf02065692264 const map = {}; result === null || result === void 0 ? void 0 : result.forEach(_ref => { let [key, value] = _ref; map[key] = value; return value; }); const reqLength = getRequests.length; /** * As mentioned few lines above, this method could be called with the array of potential error, * in case of anything goes wrong. The problem is, if any of the batched calls fails * the rest of them would fail too, but the error would be consumed by just one. The rest * would simply return `undefined` as their result, rendering false negatives. * * In order to avoid this situation, in case of any call failing, * the rest of them will be rejected as well (with the same error). */ const errorList = convertErrors(errors); const error = errorList !== null && errorList !== void 0 && errorList.length ? errorList[0] : null; for (let i = 0; i < reqLength; i++) { var _request$callback2, _request$resolve; const request = getRequests[i]; if (error) { var _request$callback, _request$reject; (_request$callback = request.callback) === null || _request$callback === void 0 ? void 0 : _request$callback.call(request, errorList); (_request$reject = request.reject) === null || _request$reject === void 0 ? void 0 : _request$reject.call(request, error); continue; } const requestResult = request.keys.map(key => [key, map[key]]); (_request$callback2 = request.callback) === null || _request$callback2 === void 0 ? void 0 : _request$callback2.call(request, null, requestResult); (_request$resolve = request.resolve) === null || _request$resolve === void 0 ? void 0 : _request$resolve.call(request, requestResult); } }); }, /** * 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. * * See https://react-native-async-storage.github.io/async-storage/docs/api#multiget */ multiGet: (keys, callback) => { if (!_immediate) { _immediate = setImmediate(() => { _immediate = null; AsyncStorage.flushGetRequests(); }); } const getRequest = { keys: keys, callback: callback, // do we need this? keyIndex: _getKeys.length, resolve: null, reject: null }; const promiseResult = new Promise((resolve, reject) => { getRequest.resolve = resolve; getRequest.reject = reject; }); _getRequests.push(getRequest); // avoid fetching duplicates keys.forEach(key => { if (_getKeys.indexOf(key) === -1) { _getKeys.push(key); } }); return promiseResult; }, /** * 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. * * See https://react-native-async-storage.github.io/async-storage/docs/api#multiset */ multiSet: (keyValuePairs, callback) => { checkValidArgs(keyValuePairs, callback); return new Promise((resolve, reject) => { keyValuePairs.forEach(_ref2 => { let [key, value] = _ref2; checkValidInput(key, value); }); RCTAsyncStorage.multiSet(keyValuePairs, errors => { const error = convertErrors(errors); callback === null || callback === void 0 ? void 0 : callback(error); if (error) { reject(error); } else { resolve(); } }); }); }, /** * Call this to batch the deletion of all keys in the `keys` array. * * See https://react-native-async-storage.github.io/async-storage/docs/api#multiremove */ multiRemove: (keys, callback) => { return new Promise((resolve, reject) => { keys.forEach(key => checkValidInput(key)); RCTAsyncStorage.multiRemove(keys, errors => { const error = convertErrors(errors); callback === null || callback === void 0 ? void 0 : callback(error); if (error) { reject(error); } else { resolve(); } }); }); }, /** * Batch operation to merge in existing and new values for a given set of * keys. This assumes that the values are stringified JSON. * * **NOTE**: This is not supported by all native implementations. * * See https://react-native-async-storage.github.io/async-storage/docs/api#multimerge */ multiMerge: (keyValuePairs, callback) => { return new Promise((resolve, reject) => { RCTAsyncStorage.multiMerge(keyValuePairs, errors => { const error = convertErrors(errors); callback === null || callback === void 0 ? void 0 : callback(error); if (error) { reject(error); } else { resolve(); } }); }); } }; })(); // Not all native implementations support merge. if (!RCTAsyncStorage.multiMerge) { delete AsyncStorage.mergeItem; delete AsyncStorage.multiMerge; } export default AsyncStorage; //# sourceMappingURL=AsyncStorage.native.js.map