2015-09-21 76 views
1

我有一個使用IndexedDB的應用程序。最初我對回調進行了大量使用,並決定使用angularjs承諾$q進行清理。Promise在angularjs中不適用於IndexedDB

失敗。

http://jsfiddle.net/ed4becky/bumm337e/

angular.module("IDBTest", []); 

angular.module("IDBTest") 
.service("initSvc", ['$q', function ($q) { 
var svc = this; 
svc.dbVersion = 1; 
svc.open = open; 
svc.deleteDB = deleteDB; 
var idb = window.indexedDB; 

function deleteDB() { 
    return $q(function (resolve, reject) { 
     idb.webkitGetDatabaseNames().onsuccess = 
      function (sender, args) { 
      if (sender.target.result 
       && sender.target.result.length > 0) { 
       var db = sender.target.result[0]; 
       console.log("deleting " + db); 
       var request = idb.deleteDatabase(db); 
       request.onsuccess = function() { 
        console.log('database ' + db + ' deleted.'); 
        resolve(); 
       }; 
       request.onerror = function() { 
        reject(); 
       }; 
      } else { 
       console.log("Nothing to delete"); 
       resolve(); 
      }; 
     }; 
    }); 
} 

function open(dbName) { 
    return $q(function (resolve, reject) { 
     var request = idb.open(dbName, svc.dbVersion); 
     request.onupgradeneeded = function (e) { 
      var db = e.target.result; 
      console.log("creating new " + db.name); 
      e.target.transaction.onerror = function (e) { 
       console.log(e); 
      }; 
      db.createObjectStore("table1", { 
       keyPath: "id" 
      }); 
      db.createObjectStore("table2", { 
       keyPath: "id" 
      }); 
      db.createObjectStore("table3", { 
       keyPath: "id" 
      }); 
     }; 

     request.onsuccess = function (e) { 
      console.log('database ' + dbName + ' open.'); 
      svc.db = e.target.result; 
      resolve(); 
     }; 

     request.onerror = function() { 
      reject(); 
     }; 

    }); 
} 
}]); 

angular.module('IDBTest') 
.factory('$exceptionHandler', ['$log', function ($log) { 
return function (exception, cause) { 
    throw exception; 
}; 
}]); 

angular.module('IDBTest') 
.run(['initSvc', function (initSvc) { 
initSvc.deleteDB() 
    .then(initSvc.open('testDatabase')) 
    .then(function() { 
     console.log(initSvc.db.name + ' initialized'); 
    }); 
}]); 

這撥弄顯示了我的期望,

  1. 創建的所有數據庫都將被刪除。 然後
  2. 數據庫是開放的觸發onupgradeneeded 然後
  3. 數據庫中引用

不幸的是,then statments似乎得到調用之前的承諾在泛美開發銀行的呼叫的onSuccess方法解決。

要重新創建,請打開控制檯運行jsfiddle。可能需要運行它幾次來獲取異常,但是它大部分時間都失敗了,因爲在調用數據庫open的onsuccess之前調用last then子句。

任何想法?

回答

2

我相信問題在於Promise Chain。 Angular的文檔有點混亂,但好像回調方法的返回值是一個承諾,它會用一個值來解析;不是承諾。因此,打破了連鎖。

Angular Promise 'Then' Method Documentation

then(successCallback, errorCallback, notifyCallback) - 無論 時的承諾是或將得到解決或拒絕,然後異步只要結果 可調用的成功或錯誤回調的一個 。回調被調用一個參數: 結果或拒絕原因。另外,在 承諾被解決或被拒絕之前,通知回叫可以是被稱爲零次或多次的 以提供進度指示。

該方法返回一個新的承諾,其解決或者經由 的successCallback,errorCallback(的返回值被拒絕,除非該 值是一個承諾,在這種情況下,它與哪個 在這種希望解決的值解析使用promise chaining)。它還通過notifyCallback方法的返回值通知 。該承諾不能通過notifyCallback方法解決或拒絕 。

我能夠得到它與這個初始化:

angular.module('IDBTest') 
    .run(['initSvc', function (initSvc) { 
    initSvc.deleteDB() 
     .then(function() { 
      return initSvc.open('testDatabase'); 
     }) 
     .then(function() { 
      console.log(initSvc.db.name + ' initialized'); 
     }); 
}]); 
+0

該訣竅。我不確定我明白爲什麼。 – ed4becky

+0

這有助於http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues – ed4becky

+0

是的,這確實有幫助。謝謝!我需要找到一個圖騰。 – Corey