Home > Technology > Html5 : stockage local & synchronisation

Html5 : stockage local & synchronisation

Date post: 10-May-2015
Category:
Author: goldoraf
View: 2,966 times
Download: 1 times
Share this document with a friend
Embed Size (px)
Popular Tags:
of 69 /69
HTML 5 stockage local & synchronisation Raphaël Rougeron @goldoraf
Transcript
  • 1.HTML 5stockage local& synchronisation Raphal Rougeron @goldoraf

2. Une mutation est en coursPages HTMLServeurClient Single-Page ApplicationJSON 3. Form validationGeolocationDrag n Drop API Web NotificationsCanvas WebGLVideo Audio File API Web WorkersWeb Sockets 4. Stockage local 5. 1er bnfice : le offline ? 6. 1er bnfice : conomiser le serveur !Source : HTML5 Web Sockets: A Quantum Leap in Scalability for the Webhttp://soa.sys-con.com/node/1315473 7. 4 tapes 8. Etape 1 Rendre les ressourcesdisponibles hors connexion 9. Application Cache CACHEMANIFEST CACHEMANIFESTCACHE: CACHE:index.html index.htmlcss/style.css css/style.cssimg/logo.png img/logo.pngjs/main.js js/main.jstext/cachemanifest 10. !Avoir un manifestechange compltementles rgles daccs aux ressources 11. CACHEMANIFEST CACHEMANIFEST#v.1.2build1234 #v.1.2build1234CACHE: CACHE:index.html index.htmlcss/style.css css/style.cssimg/logo.png img/logo.pngjs/main.js js/main.js 12. CACHEMANIFEST CACHEMANIFEST#v.1.2build1234 #v.1.2build1234CACHE: CACHE:index.html index.htmlcss/style.css css/style.cssimg/logo.png img/logo.pngjs/main.js js/main.jsNETWORK NETWORK/sync /sync/api/* /api/*http://api.twitter.com http://api.twitter.com 13. CACHEMANIFEST CACHEMANIFEST#v.1.2build1234 #v.1.2build1234CACHE: CACHE:index.html index.htmlcss/style.css css/style.cssimg/logo.png img/logo.pngjs/main.js js/main.jsNETWORK NETWORK/sync /sync/api/* /api/*http://api.twitter.com http://api.twitter.comFALLBACK FALLBACKimages/large/images/offline.jpg images/large/images/offline.jpg*.html/offline.html *.html/offline.html 14. window.applicationCache status UNCACHED IDLE CHECKING DOWNLOADING UPDATEREADY OBSOLETE 15. varappCache=window.applicationCache; varappCache=window.applicationCache;appCache.addEventListener(updateready,function(e){ appCache.addEventListener(updateready,function(e){if(appCache.status==appCache.UPDATEREADY){ if(appCache.status==appCache.UPDATEREADY){appCache.swapCache(); appCache.swapCache();if(confirm(Unenouvelleversionestdispo)){ if(confirm(Unenouvelleversionestdispo)){window.location.reload(); window.location.reload();} }} }},false); },false); 16. >= 10 ? >= 3.5 >= 4.0>= 4.0 >= 10.6>= 3.2>= 2.1>= 11.0 17. Etape 2Dcoupler lapplication durseau 18. varTodo=Backbone.Model.extend({ varTodo=Backbone.Model.extend({toggle:function(){ toggle:function(){this.save({done:!this.get("done")}); this.save({done:!this.get("done")});}, },clear:function(){ clear:function(){this.destroy(); this.destroy();} }}); });varTodoList=Backbone.Collection.extend({ varTodoList=Backbone.Collection.extend({model:Todo, model:Todo,done:function(){ done:function(){returnthis.filter(function(todo){returntodo.get(done);}); returnthis.filter(function(todo){returntodo.get(done);});}, },remaining:function(){ remaining:function(){returnthis.without.apply(this,this.done()); returnthis.without.apply(this,this.done());} }}); }); 19. Backbone.Sync create() POST /collection read() GET/collection[/id] update() PUT/collection/id delete() DELETE /collection/id 20. Etape 3Stocker localement lesdonnes 21. 3 options 22. FileSystem API!seulement 23. window.requestFileSystem=window.requestFileSystem window.requestFileSystem=window.requestFileSystem||window.webkitRequestFileSystem; ||window.webkitRequestFileSystem;window.requestFileSystem(window.TEMPORARY, window.requestFileSystem(window.TEMPORARY, 5*1024*1024,5*1024*1024,onInitFs,errorHandler); onInitFs,errorHandler);window.webkitStorageInfo.requestQuota(window.PERSISTENT, window.webkitStorageInfo.requestQuota(window.PERSISTENT,5*1024*1024, 5*1024*1024,initFS,errorHandler); initFS,errorHandler);functioninitFS(grantedBytes){ functioninitFS(grantedBytes){window.requestFileSystem(PERSISTENT,grantedBytes, window.requestFileSystem(PERSISTENT,grantedBytes,onInitFs,errorHandler); onInitFs,errorHandler);}} 24. FileErrorcodeQUOTA_EXCEEDED_ERRNOT_FOUND_ERRSECURITY_ERRINVALID_MODIFICATION_ERRINVALID_STATE_ERR 25. functiononInitFs(fs){ functiononInitFs(fs){fs.root.getFile(data.txt,{create:true},function(entry){ fs.root.getFile(data.txt,{create:true},function(entry){entry.file(function(file){ entry.file(function(file){ varreader=newFileReader(); varreader=newFileReader();reader.onloadend=function(e){ reader.onloadend=function(e){repository.init(JSON.parse(e.target.result)); repository.init(JSON.parse(e.target.result));}; };reader.readAsText(file); reader.readAsText(file); },errorHandler); },errorHandler);},errorHandler); },errorHandler);}} 26. FileEntrynamefullpathisFileisDirectoryfile()createWriter()moveTo()copyTo()remove()... 27. functionpersistData(fs,data){ functionpersistData(fs,data){fs.root.getFile(log.txt,{create:true},function(entry){ fs.root.getFile(log.txt,{create:true},function(entry){entry.createWriter(function(writer){ entry.createWriter(function(writer){writer.onwriteend=function(e){ writer.onwriteend=function(e){console.log(Writecompleted.); console.log(Writecompleted.);}; };writer.onerror=function(e){ writer.onerror=function(e){console.log(Writefailed:+e.toString()); console.log(Writefailed:+e.toString());}; };varbb=newBlobBuilder(); varbb=newBlobBuilder();bb.append(JSON.stringify(data)); bb.append(JSON.stringify(data));writer.write(bb.getBlob(text/plain)); writer.write(bb.getBlob(text/plain));},errorHandler); },errorHandler);},errorHandler); },errorHandler);}} 28. Web StoragelocalStorage et sessionStorage 29. Un simple dpt cl-valeurlocalStorage.setItem("foo","bar"); localStorage.setItem("foo","bar");localStorage.setItem("tweets",JSON.stringify(tweets); localStorage.setItem("tweets",JSON.stringify(tweets);vartweets=JSON.parse(localStorage.getItem("tweets")); vartweets=JSON.parse(localStorage.getItem("tweets")); 30. Quota de 5 Mo! Pas de transactionsPas dindexation 31. localStorage["tweets:1234"]="Loremipsum..."; localStorage["tweets:1234"]="Loremipsum...";localStorage["tweets:1235"]="Nammaurislorem..."; localStorage["tweets:1235"]="Nammaurislorem...";localStorage["tags"]=JSON.stringify(["Java","Python", localStorage["tags"]=JSON.stringify(["Java","Python","Ruby","PHP"]); "Ruby","PHP"]);localStorage["tags:Java"]=JSON.stringify([1234,1235]); localStorage["tags:Java"]=JSON.stringify([1234,1235]); 32. Trs bien support Performances API simple API synchrone Mis en avant par de nb Srialisationcompagnies/projets Requtes Complexit "indexation" manuelle Maintien intgrit 33. >= 8 >= 3.5 >= 4.0>= 4.0 >= 10.5 >= 3.2>= 2.1>= 11.0 34. localStorage adapterBackbone.sync=function(method,model,options){ Backbone.sync=function(method,model,options){varresp; varresp;varstore=model.localStorage||model.collection.localStorage; varstore=model.localStorage||model.collection.localStorage;switch(method){ switch(method){case"read":resp=model.id?store.find(model): case"read":resp=model.id?store.find(model): store.findAll();store.findAll();break; break;case"create":resp=store.create(model); case"create":resp=store.create(model);break; break;case"update":resp=store.update(model); case"update":resp=store.update(model);break; break;case"delete":resp=store.destroy(model); case"delete":resp=store.destroy(model);break; break;} }if(resp){ if(resp){options.success(resp); options.success(resp);}else{ }else{options.error("Recordnotfound"); options.error("Recordnotfound");} }}; }; 35. Petit intermdeVous connaissez Redis ?BankersBoxvarbb=newBankersBox(1); varbb=newBankersBox(1);bb.set("foo","bar"); bb.set("foo","bar");bb.get("foo");//returns"bar" bb.get("foo");//returns"bar"bb.set("count",10); bb.set("count",10);bb.incr("count");//sets"count"to11,returns11 bb.incr("count");//sets"count"to11,returns11bb.incr("newcount");//sets"newcount"to1,returns1 bb.incr("newcount");//sets"newcount"to1,returns1bb.lpush("mylist","hello"); bb.lpush("mylist","hello");bb.lrange("mylist",0,1);//returns["hello"] bb.lrange("mylist",0,1);//returns["hello"]bb.rpush("mylist","world"); bb.rpush("mylist","world");bb.lrange("mylist",0,1);//returns["hello","world"] bb.lrange("mylist",0,1);//returns["hello","world"]bb.sadd("myset","apple"); bb.sadd("myset","apple");bb.sadd("myset","oragne"); bb.sadd("myset","oragne"); 36. IndexedDB 37. Prfixes, prfixes...window.indexedDB=window.indexedDB||window.mozIndexedDB|| window.indexedDB=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB; window.webkitIndexedDB;window.IDBKeyRange=window.IDBKeyRange|| window.IDBKeyRange=window.IDBKeyRange||window.webkitIDBKeyRange; window.webkitIDBKeyRange;window.IDBTransaction=window.IDBTransaction|| window.IDBTransaction=window.IDBTransaction||window.webkitIDBTransaction; window.webkitIDBTransaction; 38. API asynchronefunctionIndexedDBAdapter(){ functionIndexedDBAdapter(){ this.db=null;this.db=null;varrequest=indexedDB.open("contactApp"); varrequest=indexedDB.open("contactApp");request.onsuccess=function(e){ request.onsuccess=function(e){ this.db=e.target.result;this.db=e.target.result;}.bind(this); }.bind(this);request.onfailure=function(e){ request.onfailure=function(e){ console.log("Couldnotconnecttothedatabase");console.log("Couldnotconnecttothedatabase");}}}; }; 39. Cration dun dptIndexedDBAdapter.prototype.create=function(storeName){ IndexedDBAdapter.prototype.create=function(storeName){ varv="1.0";varv="1.0"; varrequest=this.db.setVersion(v);varrequest=this.db.setVersion(v);request.onsuccess=function(e){ request.onsuccess=function(e){varstore=this.db.createObjectStore(storeName,{ varstore=this.db.createObjectStore(storeName,{ "keyPath":"id","keyPath":"id", "autoIncrement":true"autoIncrement":true}); });}; };request.onblocked=function(e){ request.onblocked=function(e){console.log("Thedatabaseisopeninanothertab."); console.log("Thedatabaseisopeninanothertab.");}; };}; }; 40. Persistence dun objetIndexedDBAdapter.prototype.save(storeName,object,callback) IndexedDBAdapter.prototype.save(storeName,object,callback){{ vartrans=db.transaction([storeName],vartrans=db.transaction([storeName],IDBTransaction.READ_WRITE,0); IDBTransaction.READ_WRITE,0); varstore=trans.objectStore(storeName);varstore=trans.objectStore(storeName); varrequest=store.put(object);varrequest=store.put(object);request.onsuccess=function(e){ request.onsuccess=function(e){callback(object); callback(object);}; };}; }; 41. Requte simpleIndexedDBAdapter.prototype.all(storeName,callback){ IndexedDBAdapter.prototype.all(storeName,callback){ vartrans=db.transaction([storeName],vartrans=db.transaction([storeName],IDBTransaction.READ_WRITE,0); IDBTransaction.READ_WRITE,0); varstore=trans.objectStore(storeName);varstore=trans.objectStore(storeName);varkeyRange=IDBKeyRange.lowerBound(0); varkeyRange=IDBKeyRange.lowerBound(0);varrequest=store.openCursor(keyRange); varrequest=store.openCursor(keyRange);request.onsuccess=function(e){ request.onsuccess=function(e){varcursor=e.target.result; varcursor=e.target.result;if(cursor){ if(cursor){ callback(cursor.value);callback(cursor.value); cursor.continue();cursor.continue();}}}; };}; }; 42. Key RangesIDBKeyRange.upperBound(x);//yIDBKeyRange.bound(x,y);//>=x&&=x&&x&&x&&= 10 ? >= 8.0 >= 16.0 ? ?? ?? 46. Et pourquoi pasWeb SQL Database ? 47. X X>= 4.0>= 3.1 >= 10.5>= 3.2>= 2.1>= 11.0 48. Le polyfill ultime ?Lawnchair localStorage indexedDB webkitsqlite gearssqlite ieuserdata backberrypersistentstore windowname 49. Etape 4Dvelopper une stratgie de synchronisation 50. Lexemple dActiveSync 51. POST/MicrosoftServerActiv[email protected]&...POST/[email protected]&...&Cmd=&Cmd=Cmd=FolderSync&SyncKey=123456789Cmd=FolderSync&SyncKey=123456789{{folders:[folders:[ contacts:{ contacts:{id:1234,id:1234,created:0,created:0,updated:2,updated:2,deleted:1deleted:1 }, }, todos:{ todos:{id:5678,id:5678,created:5,created:5,updated:0,updated:0,deleted:2deleted:2 } }]]}} 52. Cmd=Sync&SyncKey=123456789&FolderId=5678Cmd=Sync&SyncKey=123456789&FolderId=5678{{ syncKey:987654321, syncKey:987654321,created:[created:[{id:4321,label:"Acheterlepain"},{id:4321,label:"Acheterlepain"},...... ], ], updated:[ updated:[...... ], ], deleted:[ deleted:[5678,78905678,7890 ] ]}} 53. Autres pistesMozilla ServicesSyncMLOperational Transformation ShareJS 54. Etape subsidiaireLe "push" 55. PollingClient Serveur n secondes n secondes 56. Long polling (COMET) Client Serveurvnementct serveurvnementct serveur 57. WebSockets 58. HandshakeGET/resourcename/HTTP/1.1Upgrade:WebSocketConnection:UpgradeHost:/server/Origin:/origin/WebSocketProtocol:/protocol/HTTP/1.1101WebSocketProtocolHandshakeUpgrade:WebSocketConnection:UpgradeWebSocketOrigin:/origin/WebSocketLocation:/url/WebSocketProtocol:/subprotocol/ 59. Serveur (avec node.js) vario=require(socket.io).listen(80); vario=require(socket.io).listen(80); io.sockets.on(connection,function(socket){ io.sockets.on(connection,function(socket){socket.emit(news,{hello:world}); socket.emit(news,{hello:world});socket.on(myotherevent,function(data){ socket.on(myotherevent,function(data){ console.log(data);console.log(data);}); }); }); });Client varsocket=io.connect(http://localhost); varsocket=io.connect(http://localhost); socket.on(news,function(data){ socket.on(news,function(data){console.log(data); console.log(data);socket.emit(myotherevent,{my:data}); socket.emit(myotherevent,{my:data}); }); }); 60. >= 10 ? >= 6.0 >= 14.0 >= 5.0 >= 11.0>= 4.2? >= 11.0 61. Avec Socket.IO>= 5.5 >= 3.0 >= 4.0>= 3.0 >= 10.61 >= 3.2>= 2.1>= 11.0 62. Server-Sent Events 63. HTTP traditionnelGET/myAppStreamContentType:text/eventstream 64. if(window.EventSource){if(window.EventSource){varsource=newEventSource(myAppStream);varsource=newEventSource(myAppStream);}else{}else{//fallbacktosomething...//fallbacktosomething...}}source.addEventListener(message,function(e){source.addEventListener(message,function(e){console.log(e.data);console.log(e.data);},false);},false);source.addEventListener(open,function(e){source.addEventListener(open,function(e){},false);},false);source.addEventListener(error,function(e){source.addEventListener(error,function(e){if(e.readyState==EventSource.CLOSED){if(e.readyState==EventSource.CLOSED){}}},false);},false); 65. Format des messagesdata:HelloworldnnMulti-lignedata:Hellondata:worldnnJSONdata:{ndata:"msg":"Helloworld",ndata:"id":12345ndata:}nn 66. Format des messagesUtilisation des IDsid:12345ndata:{"user":"goldo","msg":"Hello!"}nnUtilisation des eventsdata:{"msg":"Hello!"}nnevent:loginndata:{"user":"goldo"}nnevent:updatendata:{"user":"goldo","status":"away"}nn 67. AvantagesReconnexion automatiqueIdsEvents 68. Questions / rponses


Recommended