EntityManager.saveChanges
时出现“ TypeError:对象不是函数 ”错误。在breeze向服务器发送任何内容之前出现错误。当我读取(长)堆栈跟踪时,我发现错误是在名为
InitializeEntityPrototype.prototype.getProperty
的Breeze方法中抛出的。
您可能会遇到其他地方出现此错误;这恰好是我今天发现它的地方。
请注意,我的应用程序使用Knockout(ko)。这意味着我的实体模型由微风“ko”模型适配器管理,该适配器期望 每个数据属性 为 ko.observable (an { {1}}或observable
)。这意味着您的属性值实现为函数,而不是原始数据类型,数组或对象。
Breeze用可观察的属性初始化我的实体,所以我不必自己做。但是,当我在我的代码中设置实体模型时,由保留这些可观察对象。
ko编程中最常见的错误之一是设置属性而不是调用属性设置器。
observableArray
当我错误地将“foo”分配给todo.Description("foo"); // Correct ... call the ko.observable assignment function
todo.Description = "foo"; // WRONG ... wipes out the observable function !!!
时,可观察功能就消失了...... Breeze也能够监控对该属性的更改。
我的数据绑定HTML控件似乎可以继续工作。 Knockout不必绑定到observable;它将很乐意绑定到原始数据值。但现在这变成了一次性只读绑定。该物业不再可观察。对属性的后续更改不会传播到屏幕。
换句话说,我的错误分配会导致UI行为出现无声错误。
但是当Breeze试图处理财产时,我的错误并不是沉默。 Breeze假定实体数据属性是ko函数。 Breeze ko模型适配器无需检查......它只是调用它所假定的功能。这是(内部)实体todo.Description
实现:
getProperty
如果proto.getProperty = function (propertyName) {
return this[propertyName]();
};
不是函数,你可以看到为什么会抛出异常。
可悲的是,对于我来说,错误可能会被抛到Breeze操作的深处。错误消息“对象不是函数”(或类似的东西)可能与任何事物有关。我不太可能建立连接。
这个S.O.问题是提醒我寻找这个特殊原因。
这显然是我的错。现在我必须找到我分配实体属性的位置而不是调用函数...并修复它。
我的搜索取决于知道属性名称。目前的错误消息没有告诉我名字。因此,我必须断开代码并捕获错误,因为它被抛出。
“简单”的权宜之计是使用this[propertyName]
版本在 breeze.debug.js 中暂时修补此方法。
try/catch
”将其更改为:
return this[propertyName]();
在开发者工具打开的情况下再次运行应用程序
它应该停在proto.getProperty = function(propertyName) {
try {
return this[propertyName]();
} catch (err) {
debugger;
err.message = propertyName + ' is not a ko function; did you wipe it out by assignment?\n' +
(err.message || '');
throw err;
}
}
行,在那里您将学习属性名称和所涉及的实体。
如果Breeze为我写这个消息会很好。事实上,该团队正在考虑这样做。
主要障碍是表现。 debugger
和getProperty
方法处于热门道路上。它们被调用很多,特别是在查询结果实现期间。 Breeze团队对这个敏感区域的额外逻辑持怀疑态度。我们不希望每个人都付出巨大的代价来捕捉开发者的错误,至少不是在生产(缩小的)Breeze库中。
让我们给Breeze团队时间来解决这个问题。
答案 0 :(得分:3)
您的问题写得很好,涉及到一个常见问题,并且对于搜索此特定问题的其他人可能会有所帮助。但是,它仍然可能要求意见。
无论如何......
我和我的同事从您的情况“淘汰税”中解决了这个问题:您需要处理一些编程方面的不便,以换取使用优秀的MVVM库。当您data-bind="visible: !myObservable"
并忘记将其作为获取值的函数执行时,会出现同一问题的不同实例。
回答这个问题:不,我不认为 Breeze 应该处理这个问题,至少不会有更丰富的错误信息。如果有的话,我认为如果您遇到问题,有三种不同的选择:
Description
是KnockoutObservable<string>
,那么如果您为其分配常规字符串,编译器会抱怨。但那只是我的2个cts - 阅读我自己的答案我觉得这个(“情况X应该由框架Y处理吗?”)是一个意见问题。