UNPKG

16.2 kBMarkdownView Raw
1# localForage
2
3**Offline storage, improved.**
4
5```js
6// Set a value with localStorage:
7localStorage.setItem('key', JSON.stringify('value'));
8doSomethingElse();
9
10// The same code with localForage:
11localforage.setItem('key', 'value').then(doSomethingElse);
12
13// localForage also support callbacks:
14localforage.setItem('key', 'value', doSomethingElse);
15```
16
17localForage is a JavaScript library that improves the offline experience of your web app by using an asynchronous data store with a simple, `localStorage`-like API. It allows developers to [store many types of data](#data-api-setitem) instead of just strings.
18
19localForage includes a localStorage-backed fallback store for browsers with no IndexedDB or WebSQL support. Asynchronous storage is available in the current versions of all major browsers: Chrome, Firefox, IE, and Safari (including Safari Mobile).
20
21**localForage offers a callback API as well as support for the [ES6 Promises API][]**, so you can use whichever you prefer.
22
23[Download localforage.min.js][download]
24
25[download]: https://raw.githubusercontent.com/mozilla/localForage/master/dist/localforage.min.js
26[ES6 Promises API]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
27
28# Installation
29
30```bash
31# Install via npm:
32npm install localforage
33
34# Or with bower:
35bower install localforage
36```
37
38```html
39<script src="localforage.js"></script>
40<script>console.log('localforage is: ', localforage);</script>
41```
42
43To use localForage, [download the latest release](https://github.com/mozilla/localForage/releases) or install with [npm](https://www.npmjs.org/) (`npm install localforage`) or [bower](http://bower.io/) (`bower install localforage`).
44
45Then simply include the JS file and start using localForage: `<script src="localforage.js"></script>`. You don't need to run any init method or wait for any `onready` events.
46
47# Data API
48
49These APIs deal with getting and setting data in the offline store.
50
51## getItem
52
53```js
54localforage.getItem('somekey').then(function(value) {
55 // This code runs once the value has been loaded
56 // from the offline store.
57 console.log(value);
58}).catch(function(err) {
59 // This code runs if there were any errors
60 console.log(err);
61});
62
63// Callback version:
64localforage.getItem('somekey', function(err, value) {
65 // Run this code once the value has been
66 // loaded from the offline store.
67 console.log(value);
68});
69```
70
71`getItem(key, successCallback)`
72
73Gets an item from the storage library and supplies the result to a callback. If the key does not exist, `getItem()` will return `null`.
74
75<aside class="notice">
76 Even if `undefined` is saved, `null` will be returned by `getItem()`. This is due to a [limitation in localStorage](https://github.com/mozilla/localForage/pull/42), and for compatibility reasons localForage cannot store the value `undefined`.
77</aside>
78
79## setItem
80
81```js
82localforage.setItem('somekey', 'some value').then(function (value) {
83 // Do other things once the value has been saved.
84 console.log(value);
85}).catch(function(err) {
86 // This code runs if there were any errors
87 console.log(err);
88});
89
90// Unlike localStorage, you can store non-strings.
91localforage.setItem('my array', [1, 2, 'three']).then(function(value) {
92 // This will output `1`.
93 console.log(value[0]);
94}).catch(function(err) {
95 // This code runs if there were any errors
96 console.log(err);
97});
98
99// You can even store binary data from an AJAX request.
100req = new XMLHttpRequest();
101req.open('GET', '/photo.jpg', true);
102req.responseType = 'arraybuffer';
103
104req.addEventListener('readystatechange', function() {
105 if (req.readyState === 4) { // readyState DONE
106 localforage.setItem('photo', req.response).then(function(image) {
107 // This will be a valid blob URI for an <img> tag.
108 var blob = new Blob([image]);
109 var imageURI = window.URL.createObjectURL(blob);
110 }).catch(function(err) {
111 // This code runs if there were any errors
112 console.log(err);
113 });
114 }
115});
116```
117
118`setItem(key, value, successCallback)`
119
120Saves data to an offline store. You can store the following types of JavaScript objects:
121
122* **`Array`**
123* **`ArrayBuffer`**
124* **`Blob`**
125* **`Float32Array`**
126* **`Float64Array`**
127* **`Int8Array`**
128* **`Int16Array`**
129* **`Int32Array`**
130* **`Number`**
131* **`Object`**
132* **`Uint8Array`**
133* **`Uint8ClampedArray`**
134* **`Uint16Array`**
135* **`Uint32Array`**
136* **`String`**
137
138<aside class="notice">
139 When using localStorage and WebSQL backends, binary data will be serialized before being saved (and retrieved). This serialization will incur a size increase when binary data is saved.
140</aside>
141
142<a href="http://jsfiddle.net/ryfo1jk4/161/">Live demo</a>
143
144## removeItem
145
146```js
147localforage.removeItem('somekey').then(function() {
148 // Run this code once the key has been removed.
149 console.log('Key is cleared!');
150}).catch(function(err) {
151 // This code runs if there were any errors
152 console.log(err);
153});
154```
155
156`removeItem(key, successCallback)`
157
158Removes the value of a key from the offline store.
159
160<a href="http://jsfiddle.net/y1Ly0hk1/37/">Live demo</a>
161
162## clear
163
164```js
165localforage.clear().then(function() {
166 // Run this code once the database has been entirely deleted.
167 console.log('Database is now empty.');
168}).catch(function(err) {
169 // This code runs if there were any errors
170 console.log(err);
171});
172```
173
174`clear(successCallback)`
175
176Removes every key from the database, returning it to a blank slate.
177
178<aside class="warning">
179 `localforage.clear()` will remove **every item in the offline store**. Use this method with caution.
180</aside>
181
182## length
183
184```js
185localforage.length().then(function(numberOfKeys) {
186 // Outputs the length of the database.
187 console.log(numberOfKeys);
188}).catch(function(err) {
189 // This code runs if there were any errors
190 console.log(err);
191});
192```
193
194`length(successCallback)`
195
196Gets the number of keys in the offline store (i.e. its "length").
197
198## key
199
200```js
201localforage.key(2).then(function(keyName) {
202 // Name of the key.
203 console.log(keyName);
204}).catch(function(err) {
205 // This code runs if there were any errors
206 console.log(err);
207});
208```
209
210`key(keyIndex, successCallback)`
211
212Get the name of a key based on its ID.
213
214<aside class="notice">
215 This method is inherited from the localStorage API, but is acknowledged to be kinda weird.
216</aside>
217
218## keys
219
220```js
221localforage.keys().then(function(keys) {
222 // An array of all the key names.
223 console.log(keys);
224}).catch(function(err) {
225 // This code runs if there were any errors
226 console.log(err);
227});
228```
229
230`keys(successCallback)`
231
232Get the list of all keys in the datastore.
233
234## iterate
235
236```js
237// The same code, but using ES6 Promises.
238localforage.iterate(function(value, key, iterationNumber) {
239 // Resulting key/value pair -- this callback
240 // will be executed for every item in the
241 // database.
242 console.log([key, value]);
243}).then(function() {
244 console.log('Iteration has completed');
245}).catch(function(err) {
246 // This code runs if there were any errors
247 console.log(err);
248});
249
250// Exit the iteration early:
251localforage.iterate(function(value, key, iterationNumber) {
252 if (iterationNumber < 3) {
253 console.log([key, value]);
254 } else {
255 return [key, value];
256 }
257}).then(function(result) {
258 console.log('Iteration has completed, last iterated pair:');
259 console.log(result);
260}).catch(function(err) {
261 // This code runs if there were any errors
262 console.log(err);
263});
264```
265
266`iterate(iteratorCallback, successCallback)`
267
268Iterate over all value/key pairs in datastore.
269
270`iteratorCallback` is called once for each pair, with the following arguments:
271
2721. value
2732. key
2743. iterationNumber - one-based number
275
276<aside class="notice">
277 <code>iterate</code> supports early exit by returning non `undefined` value inside `iteratorCallback` callback. Resulting value will be passed to `successCallback` as the result of iteration.
278
279 This means if you're using CoffeeScript, you'll need to manually `return` nothing to keep iterating through each key/value pair.
280</aside>
281
282# Settings API
283
284These methods allow driver selection and database configuration. These methods should generally be called before the first _data_ API call to localForage (i.e. before you call `getItem()` or `length()`, etc.)
285
286## setDriver
287
288```js
289// Force localStorage to be the backend driver.
290localforage.setDriver(localforage.LOCALSTORAGE);
291
292// Supply a list of drivers, in order of preference.
293localforage.setDriver([localforage.WEBSQL, localforage.INDEXEDDB]);
294```
295
296`setDriver(driverName)`<br>
297`setDriver([driverName, nextDriverName])`
298
299Force usage of a particular driver or drivers, if available.
300
301By default, localForage selects backend drivers for the datastore in this order:
302
3031. IndexedDB
3042. WebSQL
3053. localStorage
306
307If you would like to force usage of a particular driver you can use `setDriver()` with one or more of the following arguments:
308
309* `localforage.INDEXEDDB`
310* `localforage.WEBSQL`
311* `localforage.LOCALSTORAGE`
312
313<aside class="notice">
314 If the backend you're trying to load isn't available on the user's browser, localForage will continue to use whatever backend driver it was previously using. This means that if you try to force a Gecko browser to use WebSQL, it will fail and continue using IndexedDB.
315</aside>
316
317## config
318
319```js
320// This will rename the database from "localforage"
321// to "Hipster PDA App".
322localforage.config({
323 name: 'Hipster PDA App'
324});
325
326// This will force localStorage as the storage
327// driver even if another is available. You can
328// use this instead of `setDriver()`.
329localforage.config({
330 driver: localforage.LOCALSTORAGE,
331 name: 'I-heart-localStorage'
332});
333
334// This will use a different driver order.
335localforage.config({
336 driver: [localforage.WEBSQL,
337 localforage.INDEXEDDB,
338 localforage.LOCALSTORAGE],
339 name: 'WebSQL-Rox'
340});
341```
342
343`config(options)`
344
345Set and persist localForage options. This must be called *before* any other calls to localForage are made, but can be called after localForage is loaded. If you set any config values with this method they will persist after driver changes, so you can call `config()` then `setDriver()`. The following config values can be set:
346
347<dl>
348 <dt>driver</dt>
349 <dd>
350 The preferred driver(s) to use. Same format as what is passed to <a href="#settings-api-setdriver"><code>setDriver</code></a>, above.<br>
351 Default: <code>[localforage.INDEXEDDB, localforage.WEBSQL, localforage.LOCALSTORAGE]</code>
352 </dd>
353 <dt>name</dt>
354 <dd>
355 The name of the database. May appear during storage limit prompts. Useful to use the name of your app here. In localStorage, this is used as a key prefix for all keys stored in localStorage.<br>
356 Default: <code>'localforage'</code>
357 </dd>
358 <dt>size</dt>
359 <dd>
360 The size of the database in bytes. Used only in WebSQL for now.<br>
361 Default: <code>4980736</code>
362 </dd>
363 <dt>storeName</dt>
364 <dd>
365 The name of the datastore. In IndexedDB this is the <code>dataStore</code>, in WebSQL this is the name of the key/value table in the database. <strong>Must be alphanumeric, with underscores.</strong> Any non-alphanumeric characters will be converted to underscores.<br>
366 Default: <code>'keyvaluepairs'</code>
367 </dd>
368 <dt>version</dt>
369 <dd>
370 The version of your database. May be used for upgrades in the future; currently unused.<br>
371 Default: <code>1.0</code>
372 </dd>
373 <dt>description</dt>
374 <dd>
375 A description of the database, essentially for developer usage.<br>
376 Default: <code>''</code>
377 </dd>
378</dl>
379
380<aside class="notice">
381 Unlike most of the localForage API, the <code>config</code> method is synchronous.
382</aside>
383
384# Driver API
385
386You can write your own, custom driver for localForage since **version 1.1**.
387
388## defineDriver
389
390```js
391// Implement the driver here.
392var myCustomDriver = {
393 _driver: 'customDriverUniqueName',
394 _initStorage: function(options) {
395 // Custom implementation here...
396 },
397 clear: function(callback) {
398 // Custom implementation here...
399 },
400 getItem: function(key, callback) {
401 // Custom implementation here...
402 },
403 key: function(n, callback) {
404 // Custom implementation here...
405 },
406 keys: function(callback) {
407 // Custom implementation here...
408 },
409 length: function(callback) {
410 // Custom implementation here...
411 },
412 removeItem: function(key, callback) {
413 // Custom implementation here...
414 },
415 setItem: function(key, value, callback) {
416 // Custom implementation here...
417 }
418}
419
420// Add the driver to localForage.
421localforage.defineDriver(myCustomDriver);
422```
423
424You'll want to make sure you accept a `callback` argument and that you pass the same arguments to callbacks as the default drivers do. You'll also want to resolve or reject promises. Check any of the [default drivers][] for an idea of how to implement your own, custom driver.
425
426The custom implementation may contain a `_support` property that is either boolean (`true`/`false`) or returns a `Promise` that resolves to a boolean value. If `_support` is omitted, then `true` is the default value. You can use this to make sure the browser in use supports your custom driver.
427
428<aside class="notice">
429 These drivers are available to every instance of localForage on the page, regardless of which instance you use to add the implementation.
430</aside>
431
432[default drivers]: https://github.com/mozilla/localForage/tree/master/src/drivers
433
434## driver
435
436```js
437localforage.driver();
438// "asyncStorage"
439```
440
441`driver()`
442
443Returns the name of the driver being used, or `null` if none can be used.
444
445<aside class="notice">
446 In case that a driver fails during or right after the initialization process, then localForage will try to use the next in order driver. That is with respect to the default driver order while loading localForage or to the order the drivers were passed to `setDriver()`.
447</aside>
448
449## ready
450
451```js
452localforage.ready().then(function() {
453 // This code runs once localforage
454 // has fully initialized the selected driver.
455 console.log(localforage.driver()); // LocalStorage
456}).catch(function (e) {
457 console.log(e); // `No available storage method found.`
458 // One of the cases that `ready()` rejects,
459 // is when no usable storage driver is found
460});
461```
462
463Even though localForage queues up all of its data API method calls, `ready()` provides a way to determine whether the asynchronous driver initialization process has finished. That's useful in cases like when we want to know which driver localForage has settled down using.
464
465## supports
466
467```js
468localforage.supports(localforage.INDEXEDDB);
469// true
470```
471
472`supports(driverName)`
473
474Returns (boolean) whether `driverName` is supported by the browser.
475
476See <a href="#settings-api-setdriver"><code>setDriver</code></a> for default driver names.
477
478# Multiple Instances
479
480You can create multiple instances of localForage that point to different stores. All the configuration options used by [config](#config) are supported.
481
482## createInstance
483
484```js
485var store = localforage.createInstance({
486 name: "nameHere"
487});
488
489var otherStore = localforage.createInstance({
490 name: "otherName"
491});
492
493// Setting the key on one of these doesn't affect the other.
494store.setItem("key", "value");
495otherStore.setItem("key", "value2");
496```
497
498Creates a new instance of localForage and returns it. Each object contains its own database and doesn't affect other instances of localForage.
499
500## dropInstance
501
502```js
503localforage.dropInstance().then(function() {
504 console.log('Dropped the store of the current instance').
505});
506
507localforage.dropInstance({
508 name: "otherName",
509 storeName: "otherStore"
510}).then(function() {
511 console.log('Dropped otherStore').
512});
513
514localforage.dropInstance({
515 name: "otherName"
516}).then(function() {
517 console.log('Dropped otherName database').
518});
519```
520
521When invoked with no arguments, it drops the "store" of the current instance.
522When invoked with an object specifying both `name` and `storeName` properties, it drops the specified "store".
523When invoked with an object specifying only a `name` property, it drops the specified "database" (and all its stores).