在Breeze实体上调用ko.toJS会导致运行缓慢的脚本

时间:2014-03-21 05:01:01

标签: javascript knockout.js breeze

在任何具有导航属性的Breeze实体上调用ko.toJS(entity)或者是大对象图的一部分时,IE7-8会抱怨长时间运行的脚本错误,甚至chrome也会陷入困境超过1秒。

给出了什么?!?

1 个答案:

答案 0 :(得分:2)

我以前曾经遇到过这样的困扰,并且看到了各种论坛或Github问题,这成为了开发者的问题。我想分享一些知识,希望它能帮助别人。

问题

Breeze.js为您的客户端库或框架提供了一个对象图。在实体上调用JSON.stringify()将导致可怕的堆栈溢出,因为某些属性相互引用。示例 -

Person -> Company -> Persons

由于某人的公司导航属性也具有人员的导航属性,因此他们会继续相互找到。

ko.toJS()通过检测重复项并在此时停止序列化来解决这个问题。

为什么会慢?

序列化需要更长时间,具体取决于对象图中的实体数量。别相信我?加载你的应用程序并调用ko.toJS()然后在同一对象图中加载更多实体。这需要更长的时间,保证。问题是,即使你在一个人身上调用ko.toJS(),Knockout也没有找到重复项,直到它序列化原始人公司中的每个人。这不是Knockout和Breeze的问题 - 它是由一切都相互关联的原因引起的。

我该怎么做才能解决问题?

如果可以,使用投影查询是最佳解决方案。问题通常是我们需要更深层次的嵌套实体,而不仅仅是当前实体。如果您的实体具有包含许多相关实体的导航属性,则没有简单的方法来执行投影查询,因此我们需要以两种方式之一进一步 -

  1. 编写自定义序列化程序

  2. Vote for IdeaBlade (the company behind Breeze.js) to support unwrapping more efficiently

  3. 我的观点 - 在实体经理上公开一种方法来解开'接受以下参数 -

    entityManager.unwrap(entity || [entities], [addtlTypesToUnwrap])

    其中addtlTypesToUnwrap是一个字符串数组或逗号分隔的字符串,用于定义要解包的相关实体类型。

    使用示例 -

    var thisEntity = manager.fetchEntityByKey('Person', 1, true);
    var relatedProps = ['Company', 'Address']
    entityManager.unwrap(thisEntity, relatedProps);
    

    哪会打开人员,他们的地址,公司和公司地址(如果存在)