我使用IndexedDB在我正在开发的应用程序上离线存储数据。我的问题是在负责存储数据的函数完成之前触发了事务的OnComplete。我需要知道如何使OnComplete等待这个函数在被解雇之前完成它的工作。
这就是我所拥有的...功能populateDatabase用于存储数据。要做到这一点,其中还有其他两个。
function populateDatabase() {
var i = 0;
requestFileSystem(LocalFileSystem.PERSISTENT, 0, obtainDataFile, onError);
try {
if (localDatabase != null && localDatabase.db != null) {
console.log('Started adding records');
var transaction = localDatabase.db.transaction(osTableName, "readwrite");
if (transaction) {
transaction.oncomplete = function(event) {
console.log("transaction completed.");
localDatabase.db.close();
}
transaction.onabort = function(event) {
console.log("transaction aborted.");
localDatabase.db.close();
}
transaction.ontimeout = function(event) {
console.log("transaction timeout.");
localDatabase.db.close();
}
var store = transaction.objectStore(osTableName);
if (data.length > 0)
{
if (store)
addData(transaction, store, data, 0, true);
}
}
console.log('Finished adding records');
}
} catch (e) {
console.log(e.message);
}
}

obtainDataFile,它基本上从txt文件中读取数据并存储在Data变量
中
function obtainDataFile(fileSystem) {
var directoryEntry = fileSystem.root;
directoryEntry.getFile("EstoqueCSV.txt", {
create: true,
exclusive: false
}, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend =
function(evt) {
var csv = evt.target.result;
data = $.csv.toObjects(csv);
};
reader.readAsText(file);
}, onError)
}, onError);
}

这个递归函数用于遍历Data数组,以便逐个存储寄存器。
function addData(txn, store, records, i, commitT) {
try {
if (i < records.length) {
var rec = records[i];
var req = store.add(rec);
req.onsuccess = function(ev) {
i++;
console.log("Adding record " + i);
addData(txn, store, records, i, commitT);
}
req.onerror = function(ev) {
console.log("Failed to add record." + " Error: " + ev.message);
}
} else if (i == records.length) {
console.log('Finished adding ' + records.length + " records");
}
} catch (e) {
console.log(e.message);
}
}
&#13;
问题是我的代码在addData函数完成之前到达transaction.oncomplete。我不确定在这种情况下我应该做些什么。我一直在寻找与异步调用,回调函数等相关的主题,但仍然无法解决它。
提前感谢您的帮助。
答案 0 :(得分:1)
您必须在开始交易之前加载所有数据。从您的代码中我看不到data
已加载。否则,您的代码看起来是正确的。
答案 1 :(得分:0)
根据您的方法,我以更简单的方式缩小了您的问题,正如预期的那样,它的工作就像一个魅力。
因此,您的方法和代码看起来很干净,但由于您遇到问题,现在只能通过查看所有代码来确定确切的根本原因。
一秒钟的想法是,如果在添加数据时出现一些错误,则在添加到数据库中的数据之前可以调用transaction.oncomplete
。因此,观察控制台是否有任何错误,还要添加一个错误处理程序 - transaction.onerror
另外,尝试使用FOR循环而不是递归函数。
请注意,iOS中的IndexedDB支持是非常错误的,如果是这种情况,那么应该会出现意外情况。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Stackoverflow</title>
<script type="text/javascript" charset="utf-8">
var dbDeleteRequest = window.indexedDB.deleteDatabase("toDoList");
dbDeleteRequest.onerror = function(event) {
console.log("Error while deleting database.", true);
};
dbDeleteRequest.onsuccess = function(event) {
// Let us open our database
var DBOpenRequest = window.indexedDB.open("toDoList", 5);
DBOpenRequest.onsuccess = function(event) {
console.log('<li>Database initialised.</li>');
// store the result of opening the database in the db variable. This is used a lot below
db = DBOpenRequest.result;
// Run the addData() function to add the data to the database
addData();
};
DBOpenRequest.onupgradeneeded = function(event) {
console.log('<li>DBOpenRequest.onupgradeneeded</li>');
var db = event.target.result;
db.onerror = function(event) {
console.log('<li>Error loading database.</li>');
};
// Create an objectStore for this database //, { keyPath: "taskTitle" }); { autoIncrement : true }
var objectStore = db.createObjectStore("toDoList", { autoIncrement : true });
// define what data items the objectStore will contain
objectStore.createIndex("hours", "hours", { unique: false });
objectStore.createIndex("minutes", "minutes", { unique: false });
objectStore.createIndex("day", "day", { unique: false });
objectStore.createIndex("month", "month", { unique: false });
objectStore.createIndex("year", "year", { unique: false });
objectStore.createIndex("notified", "notified", { unique: false });
};
};
function addData() {
// Create a new object ready to insert into the IDB
var newItem = [];
newItem.push({ taskTitle: "Walk dog1", hours: 19, minutes: 30, day: 24, month: "December", year: 2013, notified: "no" });
newItem.push({ taskTitle: "Walk dog2", hours: 19, minutes: 30, day: 24, month: "December", year: 2013, notified: "no" });
newItem.push({ taskTitle: "Walk dog3", hours: 19, minutes: 30, day: 24, month: "December", year: 2013, notified: "no" });
console.log(newItem);
// open a read/write db transaction, ready for adding the data
var transaction = db.transaction(["toDoList"], "readwrite");
// report on the success of opening the transaction
transaction.oncomplete = function(event) {
console.log('<li>Transaction completed: database modification finished.</li>' + new Date());
};
transaction.onerror = function(event) {
console.log('<li>Transaction not opened due to error. Duplicate items not allowed.</li>');
};
// create an object store on the transaction
var objectStore = transaction.objectStore("toDoList");
addData2(transaction, objectStore, newItem, 0, true);
};
function addData2(txn, store, records, i, commitT) {
try {
if (i < 10000) {
var rec = records[i];
var req = store.add(rec);
req.onsuccess = function(ev) {
i++;
console.log("Adding record " + i + " " + new Date());
addData2(txn, store, records, i, commitT);
}
req.onerror = function(ev) {
console.log("Failed to add record." + " Error: " + ev.message);
}
} else if (i == records.length) {
console.log('Finished adding ' + records.length + " records");
}
} catch (e) {
console.log(e.message);
}
};
</script>
</head>
<body>
</body>
</html>
For loop方法:
for(var i =0; i < 1000; i++){
// add our newItem object to the object store
var objectStoreRequest = objectStore.add(newItem[0]);
objectStoreRequest.onsuccess = function(event) {
// report the success of our new item going into the database
console.log('<li>New item added to database.</li>' + new Date());
};
}
编辑:根据评论中的讨论
更新populateDatabase
以在调用requestFileSystem
时添加回调方法。此外,更新您的requestFileSystem
以接受另一个将要回调的参数,并在最后调用它。我认为你的requestFileSystem
有一些异步调用,因为该方法在完全完成之前就会返回。
function populateDatabase() {
var i = 0;
requestFileSystem(LocalFileSystem.PERSISTENT, 0, obtainDataFile, onError, function(){
try {
if (localDatabase != null && localDatabase.db != null) {
console.log('Started adding records');
var transaction = localDatabase.db.transaction(osTableName, "readwrite");
if (transaction) {
transaction.oncomplete = function(event) {
console.log("transaction completed.");
localDatabase.db.close();
}
transaction.onabort = function(event) {
console.log("transaction aborted.");
localDatabase.db.close();
}
transaction.ontimeout = function(event) {
console.log("transaction timeout.");
localDatabase.db.close();
}
var store = transaction.objectStore(osTableName);
if (data.length > 0)
{
if (store)
addData(transaction, store, data, 0, true);
}
}
console.log('Finished adding records');
}
} catch (e) {
console.log(e.message);
}
});
}
接受requestFileSystem
requestFileSystem(LocalFileSystem.PERSISTENT, 0, obtainDataFile, onError, callback){
//After your asynchronous processing (I am assuming based on your description of problem) is done... Probably you will have some event handler or something, so in the end of that use below call...
if (callback && typeof(callback) == 'function') {
callback(event);
}
}