Top Banner
JavaScript Persistence & Offline Storage Dec 9 2009 Alexei White (Foresee Results - Nitobi) http://ambiguiti.es @AlexeiRWhite
33
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Persistent Offline Storage White

JavaScript Persistence & Offline StorageDec 9 2009

Alexei White (Foresee Results - Nitobi)http://ambiguiti.es

@AlexeiRWhite

Page 2: Persistent Offline Storage White

What is Persistence / Storage?

• Data ‘locker’ that persists between page loads, and/or browser sessions.

• Client-side data storage vs Server-side storage.

• Browsers & JavaScript engines typically do not have file I/O capabilities.

• Many reasons to want to keep data local.

Page 3: Persistent Offline Storage White

Why Persistent Storage?

• Provide sandbox mode for online documents. (eg Word vs Google Docs)

• Persist trivial data like layout and preferences.• Eliminate unnecessary server requests.• Provide powerful data lookup capabilities

(SQL) to JavaScript apps.• Browser crash fail-safe / offline mode.• Cacheing scripts.

Page 4: Persistent Offline Storage White

Offline Storage Use Case

Page 5: Persistent Offline Storage White

Isn’t That What Cookies are For?

• Very limited storage capacity (4000 bytes per)• Limited # of cookies. (~20 max per domain,

~300 cookies max overall)• Sent to server on every request.• Useful storage needs to be in 100k+ range

contiguous.

Page 6: Persistent Offline Storage White

The Flavors of JS Persistence

Page 7: Persistent Offline Storage White

Storage Flavors

Page 8: Persistent Offline Storage White

window.name

• Very old string property of the browser’s window object.

• Used primarily for setting hyperlink targets.• Persistent across pages and domains.• Can be used before domready event.

Page 9: Persistent Offline Storage White

window.name

• Combine with JSON lib or native code for reading and writing:

// Write a structure to window.name:var myObj = { “a”:”hello world”, “b”:324234 };window.name = JSON.stringify(myObj);

// Read it back:var myObj;try {

myObj = JSON.parse(window.name);} catch(e) {}

Page 10: Persistent Offline Storage White

window.name• Completely insecure.– Same Origin Policy does not apply.– Data stored in plain text within the DOM.– Can be read outside your website.

• Tends to degrade browser performance a bit.– 2MB upper limit FF or starts to get slow.– 4MB IE same.

• Not Crash-safe.– Wont be restored even if tabs are restored after crash.– Not written to disk.

• Great place to cache trivial data or communicate inter-app.

Page 11: Persistent Offline Storage White

Flash Local Shared Object

• Key/Value pair storage object built into Flash player 6+.

• Up to 100K free. Afterward, dialogue appears asking user for permission to save more.

• Supported by virtually all browsers via ExternalInterface:– IE5+– Netscape 8+– Firefox 1+– Safari 1.3+– Opera 9+

Page 12: Persistent Offline Storage White

Flash Local Shared Object

• Step 1: Create a new Flash movie:import flash.external.ExternalInterface;

// Saves data to datastorefunction saveData(store, key, value) {

sharedObject = SharedObject.getLocal(store);sharedObject.data[key] = value;sharedObject.flush();

}

// Retrieves datafunction loadDate(store, key) {

return SharedObject.getLocal(store).data[key];}

ExternalInterface.addCallback(“saveData”, this.saveData);ExternalInterface.addCallback(“loadData”, this.loadData);

Page 13: Persistent Offline Storage White

Flash Local Shared Object

• Step 2: Embed the movie (manually or via SwfObject)

<object classid=“bla” codebase=“bla” height=“1” width=“1” id=“storageMovie”>

<param name=“movie” value=“sharedobject.swf” /><param name=“allowScriptAccess” value=“always” /><embed src=“shredobject.swf” allowScriptAccess=“always”

width=“1” height=“1” name=“storageMovie” /></object>

Page 14: Persistent Offline Storage White

Flash Local Shared Object

• Step 3: Communicate via ExternalInterface// Save$(‘storageMovie’).saveData(store,key,value);

// Loadvar result = $(‘storageMovie’).loadData(store, key);

Page 15: Persistent Offline Storage White

Flash Local Shared Object

• Gotchas:– Flash movie must be on visible portion of screen

at least once before accessing via ExternalInterface.

– If it’s not working:• Check that the movie did load.• It’s on visible portion of screen.• document.getElementById(movieId) returns an object.• allowScriptAccess = “always”

Page 16: Persistent Offline Storage White

The Lowest Common Denominator

• Flash Local Shared Object– ExternalInterface supported by all browsers.– Provides persistent offline + crash-safe support.– Has wide adoption on web.– Provides decent (~100K+) storage capacity*.– Not wiped when user clears browser cache.

* When combined with GZIP.

Page 17: Persistent Offline Storage White

Silverlight IsolatedStorage

• Silverlight has same functionality.

• More capacity (1024 KB vs 100 KB).• Binary storage format• Streamwriters / readers• Compression

http://www.shinedraw.com/data-handling/silverlight-vs-flash-local-storage/

System.IO.IsolatedStorage.IsolatedStorageFile

Page 18: Persistent Offline Storage White

Silverlight IsolatedStorage

http://www.shinedraw.com/data-handling/silverlight-vs-flash-local-storage/

using System.IO.IsolatedStorage.IsolatedStorageFile;

IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();   if(store.FileExists(FILENAME)){

      isfs = new IsolatedStorageFileStream(FILENAME, FileMode.OpenOrCreate, store);      StreamReader streamReader = new StreamReader(isfs);      string s;      while ((s = streamReader.ReadLine()) != null)          TextArea.Text += (s + '\n');      streamReader.Close();  }    // save data to local storage  IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();  IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(FILENAME, FileMode.OpenOrCreate, store);  StreamWriter streamWriter = new StreamWriter(isfs);  streamWriter.Write("New Text");  streamWriter.Flush();  streamWriter.Close();

Page 19: Persistent Offline Storage White

HTML5 Overview

• Next big update to HTML standard.• AKA “Web Applications 1.0”.• In “Last Call” state with WHATWG.• Not necessarily the future of web*.• New stuff:– Canvas tag– Rich media (video)– Storage– Doc editing– Drag and Drop

- Cross-doc messaging- History management- MIME and protocol reg.

Page 20: Persistent Offline Storage White

HTML5 Features In Jeopardy

• Canvas tag– Microsoft has VML & possibly SVG in IE9

• DOM WebDB (SQL based storage)– No for IE (lots of reasons why)– Probably not for Mozilla

• Media embedding– No for IE *– Confusion over codecs (H.264 / Ogg Theora)– Concern over Patent litigation.

Page 21: Persistent Offline Storage White

HTML5 Storage Overview

• Two kinds of storage proposed:– Key/value pair (hash) storage• Create expando properties on storage object.• Similar to Shared Local Object in flash.

– WebDB (SQLite based)• Create and populate databases right in the browser• Perform SQL queries on the fly.• Based on SQLite.

Page 22: Persistent Offline Storage White

HTML5 DOM Storage

• Hash-based storage of strings (not objects).• 10 MB per zone.• Two kinds:– sessionStorage:• Die when browser closes• Not shared between tabs

– localStorage• Crash-safe• Shared BW tabs / windows and sessions – but not

zones.

Page 23: Persistent Offline Storage White

HTML5 DOM Storage

• Reading and writing:

• Won’t work:

// Writing datasessionStorage.myKey = “Hello”;window.sessionStorage[“myKey”] = “Hello”;

window.localStorage.myKey = “Hello”;localStorage[“myKey”] = “Hello”;

sessionStorage.myObj = {a:true, b:false};console.log(sessionStorage.myObj)// “[Object object]”

Page 24: Persistent Offline Storage White

HTML5 DOM Storage

• Events (onstorage, onstoragecommit*):function handleStorageEvent(e) {

// These attributes only appear in Safarivar str = “Key: “ + e.key + “\n”;str += “Original Value: “ + e.oldValue + “\n”;str += “New Value: “ + e.newValue;alert(str);

}

// Bindings, IE then W3Cif (document.attachEvent)

document.attachEvent(“onstorage”, handleStorageEvent);else

document.body.addEventListener(“storage”, handleStorageEvent);

*IE8 only

Page 25: Persistent Offline Storage White

HTML5 DOM Storage

• Clearing:

• Iterating:

• Deleting:

sessionStorage.clear();

for (var I = 0; I < sessionStorage.length; I++) {console.log(sessionStorage[sessionStorage.key(I)]);

}

sessionStorage.removeItem(“mykey”);

Page 26: Persistent Offline Storage White

HTML5 WebDB

• Will be supported in Safari 3.1+, Opera 9.?, Chrome.

• Around 5MB per domain.• Accessible across tabs and windows.• Basic SQLite SQL language features and types

supported.• Schema versioning supported.• Transactions supported.• Tables must be created on first run.

Page 27: Persistent Offline Storage White

HTML5 Database

• Detection:

• Error trapping:

if (window.openDatabase) {// …

}

try {// DB operations go here

} catch(e) {if (e == 2) {

// Version mismatch}

}

Page 28: Persistent Offline Storage White

HTML5 Database

• Simple DB Access:

• Other parameters:

var database = openDatabase("Database Name", "Database Version");database.executeSql("SELECT * FROM test", function(result1) {   // do something with the results   database.executeSql("DROP TABLE test", function(result2) {     // do some more stuff     alert("My second database query finished executing!");   });});

openDatabase(shortName, version, displayName, maxSize)

Page 29: Persistent Offline Storage White

HTML5 Database

• Parameterized queries:

• Transactions:

transaction.executeSql(“INSERT INTO products (name, price) VALUES (?, ?);’, [“Book”, 2.01]);

myDB.transaction(function(transaction) {

// Create the products tabletransaction.executeSQL(‘CREATE TABLE products (id INTEGER

NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL DEFAULT “Widget”, price REAL NOT NULL DEFAULT 9.99);’, []);

transaction.executeSql(“INSERT INTO products (name, price) VALUES (?, ?);’, [“Book”, 2.01]);

}}

Page 30: Persistent Offline Storage White

HTML5 Database

• Selects:db.transaction( function (transaction) { var query="SELECT * FROM products”; transaction.executeSql(query, [], handleProductsQuery, errorHandler);

}, transactionErrorCallback);

function handleProductsQuery(transaction, resultSet) {for (var I = 0; I < resultSet.length; I++) {

var row = resultSet.rows.item(i);console.log(row[‘name’] + “: “ + row[‘price’]);

}}

http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/UsingtheJavascriptDatabase/UsingtheJavascriptDatabase.html#//apple_ref/doc/uid/TP40007256-CH3-SW1

Page 31: Persistent Offline Storage White

HTML5 Database

• Safari DB Inspector

Page 32: Persistent Offline Storage White

Alternatives to HTML5 WebDB

• TrimQuery - http://code.google.com/p/trimpath/wiki/TrimQuery

• CouchDB– Apache-project for RESTful JSON-based data queries.– Can solve the backend/frontend interop problem by

being available to both via HTTP requests.

• Google Gears SQLite DB. Same Interface. *• Hash-based data storage using DOM storage or

other mechanism.

* Discontinued by Google

Page 33: Persistent Offline Storage White

Questions?

• Slide deck at http://ambiguiti.es