采用以下伪代码
localforageStore.setItem('foo', 'bar')
.then(console.log('foo is persisted to disk'));
localforageStore.getItem('foo')
.then(v => console.info('foo is '+v)); // A, B or C?
是console.info:-
A。保证显示“酒吧”
B。保证显示“未定义”
C。不确定
即即使对磁盘的写入是异步的,同步读取也会从indexeddb和/或localforage内部的缓冲区中解析吗?
答案 0 :(得分:2)
我在https://github.com/localForage/localForage/blob/master/src/drivers/indexeddb.js看了localForage indexedDB驱动程序。我看不到任何缓冲。因此,getItem
没有什么可以从某个缓冲区中获取的。
更具体地说,再次查看localForage源,我可以看到setItem
和getItem
是围绕indexedDB事务的基本的承诺包装。这些包装器在事务完成时解析。这告诉我indexedDB是控制非阻塞行为而不是localForage的原因。
因此,由于indexedDB负责,这意味着我们可以查看indexedDB的行为以帮助回答您的问题。我们正在发布两个交易,每个交易都有一个请求。第一个是来自setItem
的读写事务,第二个是来自getItem
的只读事务。
通常,交易可以重叠。例如,您可以同时运行100个只读事务。但是,读写事务会阻止其他事务,以确保数据完整性。读写事务不能重叠。
由于您可以开除并忘记通话内容,因此这变得有些复杂。您可以同时初始化两个事务,而不必等到第二个事务完成才开始。请注意开始运行某项与实际将其视为运行之间的区别。
因此,查看您的代码,setItem('foo', 'bar')
启动一个读写事务,而getItem('foo')启动一个只读事务。在开始只读事务之前,您无需等待读写事务承诺包装器建立。
尽管这实际上是一种非阻塞方法,但从技术上讲,它仍在indexedDB层内进行阻塞,因为只读事务将阻塞(无限期地)同一对象存储上的先前读写事务解决。
这就是我认为引起混乱的原因。因为我们知道只读事务是在读写开始之后才启动的,所以我们知道只读事务在技术上总是会在读写事务之后才解决,因为它不可能在读写事务之前或同时解决。
因此,您可以说答案是A。。因为只读事务必须等待读写事务完成。它在localForage承诺层是不确定的,但在indexedDB事务层是不确定的。
有关详细说明,请参见规范https://www.w3.org/TR/IndexedDB-2/#transaction-construct
以下是相关部分(重点是我的部分):
如果多个读/写事务正在尝试访问同一事务 对象存储区(即,如果它们具有重叠的作用域),则交易 首先创建的必须是可以访问的事务 首先对象存储。由于之前的要求 段落,这也意味着这是唯一具有 访问对象库,直到交易完成。
在读/写事务之后创建的任何事务都必须看到 读/写事务写入的更改。因此,如果读/写 创建了事务A,然后又是另一个事务B 创建,并且两个事务具有重叠的作用域,那么B必须 查看属于该对象库的任何对象库所做的任何更改 范围重叠。由于上一段的要求, 这也意味着B交易无权访问任何 对象存储在该重叠范围中,直到A事务被 完成。
通常来说,以上要求意味着任何交易 哪个范围与读/写事务重叠,并且哪个 是在该读写事务之后创建的,因此无法并行运行 进行该读/写事务。