所以这个人的代码对封装我的 DAL 有很大帮助。我强烈建议您逐字使用他的代码。
https://gist.github.com/jgoux/10738978
你会看到他有以下方法:
self.query = function(query, bindings) {
bindings = typeof bindings !== 'undefined' ? bindings : [];
var deferred = $q.defer();
self.db.transaction(function(transaction) {
transaction.executeSql(query, bindings, function(transaction, result) {
deferred.resolve(result);
}, function(transaction, error) {
deferred.reject(error);
});
});
return deferred.promise;
};
让我们分解一下。查询函数采用查询字符串(查询参数)和 ? 的可能绑定列表。在类似“SELECT * FROM A_TABLE WHERE ID = ?”的查询中。因为他的代码是一个服务,所以 self 值指向服务本身以供将来的所有调用。该函数将对数据库执行一个事务,但它返回一个只有在数据库返回后才会履行的承诺。
他的服务提供了第二个辅助函数:fetchAll。
self.fetchAll = function(result) {
var output = [];
for (var i = 0; i < result.rows.length; i++) {
output.push(result.rows.item(i));
}
return output;
};
fetchAll 会将整个行读取到一个数组中。 fetchAll 的结果参数是在查询函数的承诺履行中传递的结果变量。
如果您将他的代码复制并粘贴到您的服务文件中,您现在就拥有了一个真正的数据库服务。您可以将该服务包装在 DAL 中。这是我的项目中的一个示例。
.service('LocationService', function ($q, DB, Util) {
'use strict';
var self = this;
self.locations = [];
self.loadLocked = false;
self.pending = [];
self.findLocations = function () {
var d = $q.defer();
if (self.locations.length > 0) {
d.resolve(self.locations);
}
else if (self.locations.length === 0 && !self.loadLocked) {
self.loadLocked = true;
DB.query("SELECT * FROM locations WHERE kind = 'active'")
.then(function (resultSet) {
var locations = DB.fetchAll(resultSet);
self.locations.
push.apply(self.locations, locations);
self.loadLocked = false;
d.resolve(self.locations);
self.pending.forEach(function (d) {
d.resolve(self.locations);
});
}, Util.handleError);
} else {
self.pending.push(d);
}
return d.promise;
};
})
这个例子有点吵,因为它有一些“线程”代码来确保如果同一个承诺被触发两次,它只针对数据库运行一次。一般要点是表明 DB.query 返回一个承诺。查询方法后面的“then”使用DB服务来获取所有数据并将其添加到我的本地内存空间中。所有这些都是由 self.findLocations 返回变量 d.promise 来协调的。
你的也有类似的代表。控制器可以将您的 DAL 服务(例如我的 LocationService)通过 AngularJS 注入其中。如果您使用 AngularJS UI,则可以让它解析数据并将其传递到列表中。
最后,我对这个人的代码的唯一问题是数据库应该来自这个代码。
var dbMaker = ($window.sqlitePlugin || $window);
原因是该插件无法在 Apache Ripple 中运行。由于该插件可以很好地镜像浏览器的 Web SQL 界面,因此这个简单的小更改将使 Ripple 能够运行您的 Ionic 应用程序,同时仍然允许您在真实设备中使用 SQLite。
我希望这有帮助。