Sean
Sean

Reputation: 878

Calling Predicate() constructor causes Knockout to throw unexplained exception.

I'm new to breeze and I can't begin to imagine what's causing this to happen. This is a two part question:

1) My function is very simple. I'm querying with two predicates:

var getUserHealthMetricFromId = function (userId, healthMetricId, forceRemote) {

            var p1 = new Predicate('userId', '==', userId);
            var p2 = new Predicate('healthMetricId', '==', healthMetricId);
            var query = EntityQuery.from('UserHealthMetrics').select('lowerValue', 'upperValue')
                .where(p1.and(p2));

            if (!forceRemote) {
                //results = getUserHealthMetricFromLocal(userId, healthMetricId);
                var query = query.using(breeze.FetchStrategy.FromLocalCache);
            }
            var promise = manager.executeQuery(query);
            return promise;
        };

While I'm debugging (Chrome) the first predicate declaration line, calling the Predicate ctor causes execution to jump to the following finally clause in Knockout-3.0.0.debug.js (line 1483):

finally {
            ko.dependencyDetection.end();
            _isBeingEvaluated = false;
        }

When I execute the "_isBeingEvaluated = false" statement, an exception is inexplicably thrown landing me here (line 2607):

        } catch (ex) {
            ex.message = "Unable to process binding \"" + bindingKey + ": " + bindings[bindingKey] + "\"\nMessage: " + ex.message;
            throw ex;
        }

Thinking this might have more to do with Knockout than with Breeze, I tested by altering the code by hardcoding the Id's so that the parameter variables (which are observables) aren't involved in calling the ctor anymore:

var p1 = new Predicate('userId', '==', 1);
var p2 = new Predicate('healthMetricId', '==', 4);

No dice. The same thing happens. When I try to step into Predicate() the same thing happens. I just throws me over to the knockout debug file.

2) In the same function, the variables I'm passing in are showing up as dependentObservables() in the debug window. These values are the product of another breeze call to the server. Why would breeze render these as dependentObservables instead of plain observables (I do not declare any computeds anywhere in the code)? Here's a quick overview of my code:

In the view model:

var latestEntriesObservable = ko.observableArray(null);

 function activate() {
            $('#rangeDialog').hide();

            var promise = Q.all([datacontext.getLatestEntries(latestEntriesObservable,  currentUserId, false),
            datacontext.getUserHealthMetrics(userHealthMetricsObservable, currentUserId, false),
            datacontext.getUserHealthMetricNames(userHealthMetricNamesObservable, currentUserId, false)]);
            return promise;
        }

var getLatestEntries = function (latestEntriesObservable, userId, forceRemote) {
            var lastEntryQuery = EntityQuery.from('LatestEntries').withParameters({ id: 1 });

            if (!forceRemote) {
                var e = getLocal('HealthMetricValues', 'healthMetricId');
                if (e.length > 0) {
                    latestEntriesObservable(e);
                    return Q.resolve();
                }
            }

            return manager.executeQuery(lastEntryQuery)
                .then(querySucceeded)
                .fail(queryFailed);


            // handle the ajax callback
            function querySucceeded(data) {
                if (latestEntriesObservable) {
                    latestEntriesObservable(data.results);
                    //latestEntriesObservable(model.toProtectedObservableItemArray(data.results));
                }
                log('Retrieved latest entries.', data, true);

            }
        };

function getLocal(resource, orderBy) {
            var query = EntityQuery.from(resource).orderBy(orderBy).withParameters({ id: 1 });
            return manager.executeQueryLocally(query);
        }

If I haven't provided enough code to help make a diagnosis I'll be happy to provide more upon request.

Any suggestions would be much appreciated!

Upvotes: 0

Views: 576

Answers (1)

Jay Traband
Jay Traband

Reputation: 17052

Ok, I think the issue is that the class is actually breeze.Predicate. In order to save typing we often assign a local variable like this.

var Predicate = breeze.Predicate;
var p1 = new Predicate('userId', '==', 1);

or you can explicitly do this via

var p1 = new breeze.Predicate('userId', '==', 1);

or

var p1 = breeze.Predicate.create('userId', '==', 1);

Presumably, you are doing the same thing with EntityQuery, i.e.

var EntityQuery = breeze.EntityQuery;

Upvotes: 2

Related Questions