From ccf9171ccc40412227c78acb087051655262e1f8 Mon Sep 17 00:00:00 2001 From: Thibaut Date: Thu, 1 Jan 2015 15:11:03 -0500 Subject: [PATCH] Lazy-load IndexedDB --- assets/javascripts/app/app.coffee | 10 +-- assets/javascripts/app/db.coffee | 116 ++++++++++++++++++------------ 2 files changed, 73 insertions(+), 53 deletions(-) diff --git a/assets/javascripts/app/app.coffee b/assets/javascripts/app/app.coffee index 44ff84e1..9aaea96e 100644 --- a/assets/javascripts/app/app.coffee +++ b/assets/javascripts/app/app.coffee @@ -61,7 +61,7 @@ bootOne: -> @doc = new app.models.Doc @DOC @docs.reset [@doc] - @doc.load @bootDB.bind(@), @onBootError.bind(@), readCache: true + @doc.load @start.bind(@), @onBootError.bind(@), readCache: true new app.views.Notice 'singleDoc', @doc delete @DOC return @@ -72,21 +72,17 @@ (if docs.indexOf(doc.slug) >= 0 then @docs else @disabledDocs).add(doc) @docs.sort() @disabledDocs.sort() - @docs.load @bootDB.bind(@), @onBootError.bind(@), readCache: true, writeCache: true + @docs.load @start.bind(@), @onBootError.bind(@), readCache: true, writeCache: true delete @DOCS return - bootDB: -> + start: -> for doc in @docs.all() @entries.add doc.toEntry() @entries.add type.toEntry() for type in doc.types.all() @entries.add doc.entries.all() @db = new app.DB() - @db.init(@start.bind(@)) - return - - start: -> @trigger 'ready' @router.start() @hideLoading() diff --git a/assets/javascripts/app/db.coffee b/assets/javascripts/app/db.coffee index 37c01e7a..96c68a32 100644 --- a/assets/javascripts/app/db.coffee +++ b/assets/javascripts/app/db.coffee @@ -4,14 +4,23 @@ class app.DB constructor: -> @useIndexedDB = @useIndexedDB() - init: (@_callback) -> - if @useIndexedDB - @initIndexedDB() - else - @callback() - return + db: (fn) -> + return fn @_db unless @useIndexedDB and @_db is undefined + + if @callback isnt undefined + _callback = @callback + @callback = => + _callback() + fn @_db + return + return + + @callback = => + @_db ?= false + delete @callback + fn @_db + return - initIndexedDB: -> try req = indexedDB.open(NAME, @indexedDBVersion()) req.onerror = @callback @@ -21,20 +30,12 @@ class app.DB @callback() return - isEnabled: -> - !!@db - - callback: => - @_callback?() - @_callback = null - return - onOpenSuccess: (event) => try - @db = event.target.result - @db.transaction(['docs', app.docs.all()[0].slug], 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937 + @_db = event.target.result + @_db.transaction(['docs', app.docs.all()[0].slug], 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937 catch - @db = null + @_db = false @callback() return @@ -53,43 +54,61 @@ class app.DB return store: (doc, data, onSuccess, onError) -> - txn = @db.transaction ['docs', doc.slug], 'readwrite' - txn.oncomplete = -> if txn.error then onError() else onSuccess() + @db (db) -> + unless db + onError() + return + + txn = db.transaction ['docs', doc.slug], 'readwrite' + txn.oncomplete = -> if txn.error then onError() else onSuccess() - store = txn.objectStore(doc.slug) - store.clear() - store.add(content, path) for path, content of data + store = txn.objectStore(doc.slug) + store.clear() + store.add(content, path) for path, content of data - store = txn.objectStore('docs') - store.put(doc.mtime, doc.slug) + store = txn.objectStore('docs') + store.put(doc.mtime, doc.slug) + return return unstore: (doc, onSuccess, onError) -> - txn = @db.transaction ['docs', doc.slug], 'readwrite' - txn.oncomplete = -> if txn.error then onError() else onSuccess() + @db (db) -> + unless db + onError() + return + + txn = db.transaction ['docs', doc.slug], 'readwrite' + txn.oncomplete = -> if txn.error then onError() else onSuccess() - store = txn.objectStore(doc.slug) - store.clear() + store = txn.objectStore(doc.slug) + store.clear() - store = txn.objectStore('docs') - store.delete(doc.slug) + store = txn.objectStore('docs') + store.delete(doc.slug) + return return - version: (doc, callback) -> - txn = @db.transaction ['docs'], 'readonly' - store = txn.objectStore('docs') + version: (doc, fn) -> + @db (db) -> + unless db + fn(false) + return - req = store.get(doc.slug) - req.onsuccess = -> callback(!!req.result) - req.onerror = -> callback(false) + txn = db.transaction ['docs'], 'readonly' + store = txn.objectStore('docs') + + req = store.get(doc.slug) + req.onsuccess = -> fn(!!req.result) + req.onerror = -> fn(false) + return return load: (entry, onSuccess, onError) -> - if @isEnabled() + if @useIndexedDB and @_db isnt false onError = @loadWithXHR.bind(@, entry, onSuccess, onError) - @loadWithIDB(entry, onSuccess, onError) + @loadWithIDB entry, onSuccess, onError else - @loadWithXHR(entry, onSuccess, onError) + @loadWithXHR entry, onSuccess, onError loadWithXHR: (entry, onSuccess, onError) -> ajax @@ -99,14 +118,19 @@ class app.DB error: onError loadWithIDB: (entry, onSuccess, onError) -> - txn = @db.transaction [entry.doc.slug], 'readonly' - store = txn.objectStore(entry.doc.slug) + @db (db) -> + unless db + onError() + return + + txn = db.transaction [entry.doc.slug], 'readonly' + store = txn.objectStore(entry.doc.slug) - req = store.get(entry.path) - req.onsuccess = -> if req.result then onSuccess(req.result) else onError() - req.onerror = onError + req = store.get(entry.path) + req.onsuccess = -> if req.result then onSuccess(req.result) else onError() + req.onerror = onError - txn + txn reset: -> try indexedDB?.deleteDatabase(NAME) catch