我想编写一个Angular模块,在本地保存数据(使用IndexedDB),并通过RESTful服务将数据与服务器数据同步。
我已经为那些已经可以将数据传输到服务器并将其放入IndexedDB的基础构建了一个基础。
由于Web应用程序也必须在脱机模式下运行,因此我选择使用两个键作为对象库。 autoIncremented的本地ID和服务器上条目的ID。
服务器不知道本地ID,如果无法将服务器ID传输到服务器,本地数据条目可能不知道
当我为服务器ID定义唯一索引时,如果服务器ID已存在且更新过程停止,则本地条目将不会更新。
有没有办法直接使用IDB API?
我发现了类似的问题,但是使用简单的游标和cursor.update解决方案,不可能将新数据从服务器插入本地数据库: Indexeddb - Update record by index key
答案 0 :(得分:0)
我找到了一种方法。我将与服务器数据分开处理本地数据(带有本地ID)(没有本地ID,因为服务器不知道它)。
然后我将使用IDBObjectStore.put
更新本地数据,并检查来自服务器的数据(服务器ID是否已设置,但没有本地ID)是否已在本地保存,并具有单独的IDBIndex.openCursor
调用。如果在给定的serverId中找到了本地数据,则会添加一个带有IDBObjectStore.put
的新条目,如果找到,则该条目上的光标将使用服务器数据进行更新(旧的localId将被转移)。
// var _db => connected database
// filter the data that came from the server (no local id defined but server id is)
var serverData = [];
for (var i = 0; i < data.length; i++) {
if (data[i]._localId === undefined && data[i].serverId !== undefined && data[i].serverId !== null) {
// remove the server data object and add it to the server data array
serverData = serverData.concat(data.splice(i, 1));
i--;
}
}
var transaction = _db.transaction(_storageName, 'readwrite');
transaction.oncomplete = function() {
// do something on completion
};
transaction.onerror = function(e) {
// do something when an error occurs
};
var objectStore = transaction.objectStore(_storageName);
// Add local data to the database (no server id)
// local id can be existing or not (new entry)
for (var i = 0; i < data.length; i++) {
objectStore.put(data[i]).onsuccess = function(e) {
// do something when successfully added
};
}
// Add data from the server to the database
var index = objectStore.index('serverId'); // server id index for searching
// go through all data from the server
for (var i = 0; i < serverData.length; i++) {
(function(){
var serverItem = serverData[i];
// search for an existing entry in the local database
var checkRequest = index.openCursor(IDBKeyRange.only(serverItem.serverId));
checkRequest.onsuccess = function (e) {
var cursor = e.target.result;
// If item was not found in local indexedDB storage...
if (cursor === null) {
// add new item to storage
this.source.objectStore.put(serverItem).onsuccess = function(e) {
// do something when successfully added
};
// Item was found locally
} else {
var dbItem = cursor.value;
// set local id of the added item to the one from the old local entry
serverItem.localId = dbItem.localId;
// update found local entry with the one from the server
cursor.update(serverItem).onsuccess = function(e) {
// do something on success
};
}
};
})();
}
可能会有一个更优雅的解决方案,但这个是我提出的第一个解决方案。我会感谢任何改进或更好的解决方案。