我对Ionic和Angular都很新。我正在尝试写一个SQLite数据库,它间歇性地成功。当我执行for循环并快速插入记录时,一些成功并且一些失败(没有明显错误)。查询执行使用promises,因此多个查询可能正在尝试并发执行。这似乎导致SQLite中的同步问题 - 或SQLite插件。我尝试在每个execute()上打开一个新的数据库连接,在每个execute()上重新打开现有连接,并且我还尝试在app.js中全局打开一次连接并重用该连接。他们似乎表现得一样。
自定义'dbQuery'函数用于构建查询并且是可链接的。我的想法是,我的应用程序中有权访问数据库服务的任何地方都可以执行查询,并期望结果流入“out”变量,如:
<div>
<canvas width="300"
height="300"
id="myCanvas"
tag-canvas
canvas-id="tags"
outline-colour="#ff00ff"
text-font="Arial"
text-colour="#ff00ff"
reverse="true"
depth="0.8"
max-speed="0.05"
weight-mode="both"
weight="true"></canvas>
</div>
<div id="tags" style="font-size: 50%;">
<a ng-repeat="word in wordList" href="{{word.href}}" style="font-size: {{word.fontSize}}">{{word.text}}</a>
</div>
这很有效,但问题来自写作:
var my_query_results = [];
DB.begin().select("*","table1").execute(my_query_results).then(function() {
console.log("Query complete");
});
有时它会在没有任何记录或明显错误的情况下失败,有时会成功。如果我随着时间的推移缓慢地执行插入,它似乎没有问题。
app.js
var records = [
{id:1, name:"Bob"},
{id:2, name:"John"},
{id:3, name:"Jim"},
];
for (var i = 0; i < records.length; i++) {
var obj = records[i];
var result = [];
DB.begin().debug(true).insert("table1", "(id,name)", "("+obj.id+","+ obj.name+")").execute(result).then(function () {
console.log("Inserted record", JSON.stringify(obj));
});
}
services.js
var db;
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
.run(function ($ionicPlatform, $cordovaSQLite, appConfig, $q) {
$ionicPlatform.ready(function () {
db = $cordovaSQLite.openDB({
name: appConfig.sqlite_db,
location: appConfig.sqlite_db_location
});
dbQuery = function () {
this.bDebug = false;
this.query = "";
this.result = [];
this.params = [];
this.debug = function (value) {
this.bDebug = (value === true ? true : false);
return this;
};
this.rawQuery = function (query) {
this.query = query;
return this;
};
this.insert = function (table, fields, values) {
this.query = "INSERT INTO '" + table + "' (" + fields + ") VALUES (" + values + ")";
return this;
};
this.select = function (fields, table) {
this.query = "SELECT " + fields + " FROM " + table;
return this;
};
this.delete = function (query) {
this.query = "DELETE FROM " + query;
return this;
};
this.where = function (column, expression, value) {
expression = expression || "=";
this.query += " WHERE `" + column + "` " + expression + " ? ";
this.params[this.params.length] = value;
return this;
};
this.and = function (column, expression, value) {
expression = expression || "=";
this.query += " AND '" + column + "' " + expression + " ? ";
this.params[this.params.length] = value;
return this;
};
this.execute = function (out_var) {
var self = this;
this.result = out_var;
if (this.bDebug) {
console.log("Compiled query is", this.query);
}
var deferred = $q.defer();
db.open(function () {
console.log("Opened");
}, function () {
console.log("Failed");
});
//actually execute the query
$cordovaSQLite.execute(db, this.query, this.params).then(
function (res) {
for (var i = 0; i < res.rows.length; i++) {
self.result.push(res.rows.item(i));
console.log("Added row to set", JSON.stringify(res.rows.item(i)));
}
if (res.rows.length == 0 && self.bDebug === true) {
console.log("No results found ");
}
deferred.resolve();
}, function (err) {
console.error(JSON.stringify(err), this.query);
deferred.reject();
});
return deferred.promise;
}
我确定我遗漏了有关角度,承诺和sqlite锁定的基本信息。如果有人有建议我真的很感激。
答案 0 :(得分:0)
我按照这里的优秀建议解决了这个问题 - Angular/Ionic and async SQLite - ensuring data factory initialised before return
关键问题是我需要将所有数据库操作包装在promises中,并将它们用于有序初始化和回调。
.factory('DB', function ($q, $cordovaSQLite, appConfig) {
//private variables
var db_;
// private methods - all return promises
var openDB_ = function (dbName, location) {
var q = $q.defer();
try {
db_ = $cordovaSQLite.openDB({
name: dbName,
location: location
});
q.resolve(db_);
} catch (e) {
q.reject("Exception thrown while opening DB " + JSON.stringify(e));
}
return q.promise;
};
var performQuery_ = function (query, params, out) {
var q = $q.defer();
params = params || [];
out = out || [];
//open the DB
openDB_(appConfig.sqlite_db, appConfig.sqlite_db_location)
.then(function (db) {
//then execute the query
$cordovaSQLite.execute(db, query, params).then(function (res) {
//then add the records to the out param
console.log("Query executed", JSON.stringify(query));
for (var i = 0; i < res.rows.length; i++) {
out.push(res.rows.item(i));
console.log("Added row to set", JSON.stringify(res.rows.item(i)));
}
if (res.rows.length == 0 && self.bDebug === true) {
console.log("No results found ");
}
}, function (err) {
console.log("Query failed", JSON.stringify(query));
q.reject();
});
db_.open(function () {
q.resolve("DB Opened")
}, function () {
q.reject("Failed to open DB");
});
}, function (err) {
console.log(JSON.stringify(err), this.query);
q.reject(err);
});
return q.promise;
};
// public methods
var execute = function (query, params, out) {
var q = $q.defer();
performQuery_(query, params, out).then(function () {
q.resolve([query, params]);
}, function (err) {
q.reject([query, params, err]);
});
return q.promise;
};
return {
execute: execute
};
})