问题
I got a "TypeError: object is not a function" error when
EntityManager.saveChanges
. The error arises before breeze sends anything to the server.When I read the (long) stack trace, I see that the error is thrown inside a Breeze method called
InitializeEntityPrototype.prototype.getProperty
.
还有其他地方可能会遇到此错误;这恰好是我今天发现它的地方。
原因
请注意,我的应用程序使用 Knockout (ko)。这意味着我的实体模型由期望 的 Breeze “ko”模型适配器管理。每个数据属性 成为 ko.observable (
observable
或 observableArray
)。这意味着您的属性值实现为 功能 ,而不是原始数据类型、数组或对象。Breeze 用可观察的属性初始化我的实体,所以我不必自己做。但这取决于我在我的代码中设置实体模型时保留这些可观察值 .
ko 编程中最常见的错误之一是设置属性而不是调用属性 setter 。
todo.Description("foo"); // Correct ... call the ko.observable assignment function
todo.Description = "foo"; // WRONG ... wipes out the observable function !!!
当我错误地将“foo”分配给
todo.Description
时,可观察函数消失了……Breeze 监视该属性更改的能力也消失了。我的数据绑定(bind) HTML 控件可能会继续工作。 Knockout 不必绑定(bind)到 observable;它将愉快地绑定(bind)到原始数据值。但现在这变成了 一次性只读绑定(bind) .该属性不再是可观察的。对该属性的后续更改将不会传播到屏幕。
换句话说,我的错误分配会导致 UI 行为出现静默错误。
但是当 Breeze 尝试处理该属性时,我的错误并没有沉默。 Breeze 假设实体数据属性是一个 ko 函数。 Breeze ko 模型适配器不需要检查......它只是调用它假定的函数。这是(内部)实体
getProperty
执行:proto.getProperty = function (propertyName) {
return this[propertyName]();
};
如果
this[propertyName]
,您可以看到为什么会抛出异常。是函数以外的任何东西。对我来说可悲的是,这个错误很可能是在 Breeze 操作的深处发生的。错误消息“对象不是函数”(或类似的东西)可能是关于任何东西的。我不太可能建立联系。
这个 S.O.问题提醒您寻找这个特定的原因。
该怎么办?
这分明是我的错。现在我必须找到我分配实体属性的位置而不是调用函数......并修复它。
我的搜索取决于知道属性名称。当前的错误消息没有告诉我名称。所以我必须对代码进行断点并在抛出错误时捕获它。
一个“简单”的权宜之计是用
try/catch
临时在 Breeze .debug.js 中对这个方法进行修补。版本。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;
}
}
它应该停在
debugger
您将在其中了解属性名称和所涉及的实体的行。Breeze 是否应该提供更丰富的错误信息?
如果 Breeze 为我撰写此消息,那就太好了。事实上,团队正在考虑这样做。
主要障碍是性能。
getProperty
和 setProperty
方法正走在热门道路上。他们经常被调用,尤其是在查询结果实现期间。 Breeze 团队对这个敏感领域的额外逻辑持谨慎态度。我们不希望每个人都付出高昂的代价来捕捉开发人员错误,至少不是在生产(缩小)Breeze 库中。让我们给 Breeze 团队时间来解决这个问题。
最佳答案
您的问题写得很好,涉及一个常见问题,并且可能对其他搜索此特定问题的人有所帮助。但是,它可能仍在征求意见。
任何状况之下...
我和我的同事将您的情况中的问题称为“knockout 税”:您必须处理一些编程不便,以换取使用出色的 MVVM 库。当您使用 data-bind="visible: !myObservable"
时,会出现相同问题的不同实例。并忘记将其作为函数执行以获取值。
回答这个问题:不,我认为 Breeze 不应该处理这个问题,至少不应该使用更丰富的错误消息。如果有的话,我认为如果您处于问题的情况下,有三种不同的选择:
Description
是 KnockoutObservable<string>
如果您为其分配常规字符串,则编译器会提示。 但这只是我的 2 cts - 阅读我自己的答案,我确实觉得这(“情况 X 应该由框架 Y 处理吗?”)都是见仁见智的问题。
关于knockout.js - "TypeError: object is not a function"使用 knockout 和 Breeze 时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27713308/