采用以下伪代码
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 :-
即使写入光盘是异步的,是否会从indexeddb和/或localforage内部的缓冲区解析同步读取?
我查看了https://github.com/localForage/localForage/blob/master/src/drivers/indexeddb.js上的localForage indexedDB驱动程序。我没有看到任何缓冲。因此,getItem
没有任何东西可以从缓冲区中获取。
更具体地说,再次查看localForage源代码,我可以看到setItem
和getItem
是indexedDB事务的基本promise包装器。这些包装器在事务完成时解析。这告诉我indexedDB控制非阻塞行为,而不是localForage。
因此,因为indexedDB负责,这意味着我们可以查看indexedDB行为以帮助回答您的问题。我们发出两个交易,每个交易都有一个请求。第一个是来自setItem
的readwrite事务,第二个是来自getItem
的只读事务。
通常,交易可以重叠。例如,您可以同时运行100个只读事务。但是,readwrite事务会阻止其他事务以确保数据完整性。 readwrite事务不能重叠。
由于您可以触发并忘记呼叫事件,这会变得有点复杂。您可以同时初始化两个事务,而无需等到第一个完成后才开始第二个事务。注意开始运行某些东西之间的区别,实际上它被认为是在运行。
因此,查看代码,setItem('foo', 'bar')
启动一个readwrite事务,getItem('foo')启动一个只读事务。在启动只读事务之前,您不是在等待readwrite事务承诺包装器解决。
虽然表面上确实是一种非阻塞方法,但它仍然在indexedDB层中技术上是阻塞的,因为readonly事务将阻塞(等待,无限期地)同一对象存储上的先前读写事务来解决。
这就是我认为引起混乱的原因。因为我们知道readonly事务是在readwrite启动后启动的,所以我们知道readonly事务在技术上总是只在readwrite事务之后解析,因为它不可能在它之前解析,也不能在它同时解析。
因此,您可以说答案是A.因为只读事务必须等待readwrite事务完成。它在localForage promise层是不确定的,但在indexedDB事务层确定。
请查看规格,了解https://www.w3.org/TR/IndexedDB-2/#transaction-construct的更多技术说明
这是一个相关部分(强调我的):
如果多个读/写事务试图访问同一个对象存储(即,如果它们具有重叠的范围),则首先创建的事务必须是首先访问对象存储的事务。由于前一段中的要求,这也意味着它是唯一可以在事务完成之前访问对象存储的事务。
在读/写事务之后创建的任何事务都必须看到读/写事务所写的更改。因此,如果创建了读/写事务A,并且稍后创建了另一个事务B,并且这两个事务具有重叠的范围,则B必须看到对作为该重叠范围的一部分的任何对象存储所做的任何更改。由于前一段中的要求,这也意味着在A事务完成之前,B事务不能访问该重叠范围内的任何对象存储。
一般而言,上述要求意味着任何与读/写事务具有重叠范围并且在该读/写事务之后创建的事务不能与该读/写事务并行运行。