概述:我试图避免从网页和网络工作人员访问 IndexedDB 时出现竞争情况。
Setup:当用户使用站点时将项目保存到本地 IndexedDB 的网页。每当用户将数据保存到本地数据库时,记录就会被标记为“未发送”。
Web-worker 后台线程从 IndexedDB 中提取数据,将其发送到服务器,服务器收到数据后,将 IndexedDB 中的数据标记为“已发送”。
Problem:由于对 IndexedDB 的访问是异步的,我不能保证用户不会在网络工作人员将记录发送到服务器的同时更新记录。时间线如下所示:
- Web-worker从DB获取数据并将其发送到服务器
- 在传输发生时,用户更新将其保存到数据库的数据。
- 网络工作者从服务器获取响应,然后将数据库更新为“已发送”
- DB中现在有数据尚未发送到服务器但标记为“已发送”
失败解决方案:从服务器获得响应后,我可以重新检查行以查看是否有任何更改。然而,我仍然留下一个小窗口,可以在其中将数据写入数据库,但永远不会发送到服务器。
例子:
服务器表示数据已保存后,然后:
IndexedDB.HasDataChanged(
function(changed) {
// Since this is async, this changed boolean could be lying.
// The data might have been updated after I checked and before I was called.
if (!changed){
IndexedDB.UpdateToSent() }
});
其他注意事项:根据 W3 规范,有一个同步 api,但尚未有人实现它,因此无法使用它(http://www.w3.org/TR/IndexedDB/#sync-database)。同步 api 旨在供网络工作者使用,以避免我假设的这种情况。
任何对此的想法将不胜感激。已经研究了大约一周,但还没有想出任何可行的办法。
我想我现在找到了解决这个问题的方法。并不像我想要的那么干净,但它似乎是线程安全的。
每当我更新数据时,我首先将日期时间存储到 LastEdit 字段中。
我从网络工作者那里向浏览器发布一条消息。
self.postMessage('UpdateDataSent#' + data.ID + '#' + data.LastEdit);
然后在浏览器中,只要上次编辑日期没有改变,我就会更新我的发送标志。
// Get the data from the DB in a transaction
if (data.LastEdit == lastEdit)
{
data.Sent = true;
var saveStore = trans.objectStore("Data");
var saveRequest = saveStore.put(data);
console.log('Data updated to Sent');
}
由于这一切都是在浏览器端的事务中完成的,因此看起来工作正常。一旦浏览器支持 Sync API,我就可以把它全部扔掉。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)