Gar*_*ary 4 javascript json indexeddb
我对 JSON.stringify 的序列化步骤与将对象写入 indexedDB 中的对象存储的序列化步骤之间在浏览器/CPU/内存效率方面的差异感兴趣。
该问题的动机或上下文是以最有效的方式将对象从数据库写入客户端的硬盘驱动器。为此,使用 get 语句检索对象并将其写入对象,该对象使用 JSON.stringify 转换为字符串,然后作为文本写入磁盘。我假设 get 语句将对象从数据库中的序列化形式反序列化。如果是这样,则该对象将从 indexedDB 形式反序列化,然后序列化为 JSON.stringify 形式。
然后,为了从磁盘恢复数据,读取文件,使用 JSON.parse 将文本转换为对象,并将该对象添加或放入数据库中,这似乎需要另一个序列化步骤。因此,JSON字符串被解析为一个对象,然后序列化为indexedDB形式。
我的问题的第一部分是可以以序列化形式从数据库中检索对象,以便可以以相同的形式将其保存到磁盘并再次写入数据库,而无需执行字符串化/解析的中间步骤?
问题的第二部分是,如果不可能这样做,并且对于使用没有任何索引的indexedDB并且从不通过除外线唯一键之外的任何值查询数据的特殊情况,是否有任何优势将字符串化对象存储到数据库而不是对象?
在这种情况下,写入/读取磁盘不会涉及中间的字符串化/解析步骤,并且当字符串在数据库中获取/放入时不会有反序列化/序列化步骤,因为它不是对象。但是,要更改数据库中这些字符串之一中的值,需要对 get 的结果执行 JSON.parse 以将其转换为对象,然后在更改值后将字符串放回数据库之前执行 JSON.stringify数据库。
但是,当对对象使用 get 和 put 时,JSON.parse 和 JSON.stringify 与数据库对象的反序列化和重新序列化相比如何呢?我认为将对象序列化到 indexedDB 需要的不仅仅是 JSON.stringify,因为前者可以通过其属性进行查询。
我将进行实验,看看是否可以观察到差异,但想询问了解两种类型序列化内部工作原理的人,在这种情况下是否存在根本原因,需要使用一种方法而不是另一种方法。
编辑
显然,如果我理解正确的话,结构化克隆算法用于在indexedDB中存储对象;但该结果在存储之前仍然是序列化的吗?JSON 使用词法语法但从不复制对象。
也许,我只是很困惑,写入 indexedDB 时没有序列化步骤,而且我观察到 RAM 使用量的增加是为了克隆对象,然后将其存储为对象。如果是这样,那么问题的第一部分根本没有意义,因为数据库对象始终需要转换为字符串才能保存到磁盘。我的问题的第二部分将成为对浏览器的要求更高,1)将对象转换为字符串或克隆它,2)从数据库检索对象与检索字符串(如果保存为 JSON 字符串)并解析它?
在找到更多有关此问题的信息后,尽管其中大部分内容超出了我的理解范围,但我不确定这个问题是否值得考虑。
谢谢。
例子:
@Sam152你是说你发现,在类似下面的内容中,stingify版本比仅仅将对象放入数据库更快?第一个示例是五十个事务的间隔,第二个示例是put单个事务中的五十个事务。
// var o = A large object.
var d;
write.x = 0;
write.y=[];
DB_open().then( inter );
function inter() { d = setInterval( write, 1000 ); }
function write()
{
let T = DB_open.base.transaction( [ 'os_name' ], 'readwrite' ),
q = T.objectStore( 'os_name' ),
start = Date.now();
T.oncomplete = function() { write.y.push( Date.now() - start ); }
if ( write.x < 50 )
write.x = write.x + 1;
else
{
clearInterval(d);
console.log( 'done' );
};
o.key = write.x;
q.put( o );
// OR
q.put( { 'key' : write.x, 'd' : JSON.stringify( o ) } );
} // close write
// When complete.
total = 0;
write.y.forEach( ( v ) => { total = total + v; } );
Run Code Online (Sandbox Code Playgroud)
或者,put同一事务中的多个语句。
function write()
{
let T = DB_open.base.transaction( [ 'os_name' ], 'readwrite' ),
q = T.objectStore( 'os_name' ),
start = Date.now(),
i;
T.oncomplete = function()
{ console.log( 'Completed : ' + ( Date.now() - start ) ); }
for ( i = 1; i < 51; i++ )
{
o.key = i;
q.put( o );
// OR
q.put( { 'key' : i, 'd' : JSON.stringify( o ) } );
};
} // close write
Run Code Online (Sandbox Code Playgroud)
将对象转换为字符串并将字符串存储在数据库中没有任何性能优势。使用 JSON.stringify 将对象转换为字符串只会增加必须执行的步骤数。我强烈建议不要这样做,甚至不要尝试这样做,也不要试图超越 C++ 中的 indexedDB 实现。
indexedDB 序列化在 C++ 中进行,而不是 js。JSON.stringify 发生在 js 中,而不是 C++ 中。大多数时候,js 中发生的任何事情都比 C++ 慢几个数量级。
一个js字符串就是一个js对象。如果我没记错的话,你不能将字符串作为对象存储在indexedDB中,因为它本身是一个函数对象,而不是一个普通对象。说明这一点的另一种方式是考虑对象类型层次结构。一切都从 延伸而来Object。Function从对象延伸。String延伸自Function(好吧,也许不是直接或明确,但仍然有效)。任何从 扩展的后代Function(例如使用class Fooorfunction Foo() {}; new Foo();或创建的任何内容new Function('foo');)都是不可序列化的。任何从 扩展Object而不从 扩展的东西Function都是可序列化的。
正如我对您的其他问题的回答中所解释的,函数不可序列化。
当您使用对象字面量语法创建 js 对象时,这只是近似于 的语法糖new Object(),而不是function Foo()。这些对象很容易序列化,因为它们基本上只是字典。也就是说,直到您附加一个方法为止。方法只不过是作为属性绑定到对象的函数。因为即使是具有至少一种方法的普通对象也不再可序列化。
您不能尝试将字符串直接存储在 indexedDB 中,因为它本身是一个对象( 的后代Function),而只能将字符串存储为非函数对象的其他对象的属性,因为 indexedDB 具有对 String 类型的明确了解并明确声明支持使用字符串值存储对象属性,因为它知道如何在序列化期间强制这些值。
结构化克隆算法前段时间被重新命名。我忘记了,现在是序列化算法或类似“可转移”算法的东西。
当你在indexedDB中存储一个对象时(例如{x:1,y:2}),它将从JS发送到C++,然后在C++中它将被序列化。当你从indexedDB检索一个对象时,在C++中,它会找到串行形式的对象,反序列化它,然后将其传递给JS,然后JS将其传递回给你(你的函数或返回值)。尽管序列化更具体地指的是另一种类型到字符串的转换,但您也可以更通用地使用它来指代两个方向,因此请记住,技术文档中任何地方提到的序列化实际上可能是在谈论反序列化。
这种C++序列化不一定是从对象到字符串或字符串到对象,而是某种优化的字节格式。在 C++ 领域,有时区分字符串和其他值类型不太有用,因为字符串只是字节的一种任意表示形式。因此,当我们谈论 C++ 中的序列化时,我们只是在谈论更改抽象字节组的表示形式。很像 C 中的结构只是分解成多个部分的字节序列的表示。从某种意义上说,在 C++ 中,字符串可以被理解为零成本抽象,具体取决于它的使用方式。事实上,将某些字节组称为一种类型或另一种类型实际上只是为了澄清应该对这些字节调用哪些操作,以及这些字节应该具有什么含义。从某种意义上说,这里的序列化实际上可能只是用不同的名称调用相同的字节序列,而不实际执行任何处理!事实上,如果您曾经在文本编辑器中打开过二进制文件,或者打开过错误编码(或编码解释)的网页,您可能已经亲眼目睹了这一点。因此,如果您谈论的是性能上的差异,那么,将 0 步操作与 n 步操作进行比较会产生一个明显的答案。
也就是说,具有讽刺意味的是,C++ 序列化可能最终会转换为字符串,谁知道呢,你不应该知道,这取决于 indexedDB C++ 实现来决定这一点并将其从你手中抽象出来并隐藏其复杂性。有效存储一堆字节还存在各种其他问题,这些问题远远超出了序列化性能的范围。
总而言之,序列化在 C++ 中的含义与 JSON.stringify 在 Javascript 中的含义不同。在 js 中将值转换为字符串只会减慢程序速度。让indexedDB 为您解决这个问题。