Knockout.js Breeze多次查询淘汰可观测数组

Knockout.js Breeze多次查询淘汰可观测数组,knockout.js,asp.net-mvc-4,breeze,Knockout.js,Asp.net Mvc 4,Breeze,我被困在这一点上,无法继续 我正在通过以下方式为搜索表单创建ViewModel: var viewModel = new SearchViewModel("Api/Vehicle", "Vehicles"); ko.applyBindings(viewModel); 稍后,当用户单击“查找”按钮时,将触发“查找”方法(此处简化): query*方法仅将数据放入Knockout.js可观察数组中: function querySucceeded(data) { data.results.

我被困在这一点上,无法继续

我正在通过以下方式为搜索表单创建ViewModel:

var viewModel = new SearchViewModel("Api/Vehicle", "Vehicles");
ko.applyBindings(viewModel);
稍后,当用户单击“查找”按钮时,将触发“查找”方法(此处简化):

query*方法仅将数据放入Knockout.js可观察数组中:

function querySucceeded(data) {
    data.results.forEach(function (item) {
        self.results.push(item);
    });

    return true;
}

function queryFailed(error) {
    var erroboj = { message: error.message };
    self.errors.push(erroboj);
    return false;
}
问题是querySucceeded从未被调用,Knockout.js的数据也从未更新,从而触发数据绑定

我做错了什么


这是ViewModel。还有点不完整和模糊。 我想我没有正确理解breeze query Promiss:

/*global $, jQuery, ko, breeze, bootstrap */

function SearchViewModel(serviceName, actionName) {
    "use strict";
    var self = this;

    self.serviceName = serviceName;
    self.actionName = actionName;
    self.errors = ko.observableArray([]);
    self.results = ko.observableArray([]);

    self.CreateEntity = function (entityTypeName) {
        var entityType = self.manager.metadataStore.getEntityType(entityTypeName),
            newEntity = entityType.createEntity();
        return self.manager.addEntity(newEntity);
    };

    function querySucceeded(data) {
        // Here the function I want to run
        data.results.forEach(function (item) {
            self.results.push(item);
        });

        return true;
    }

    function queryFailed(error) {
        var erroboj = { message: error.message };
        self.errors.push(erroboj);
        return false;
    }

    function addError(errorMessage) {
        var erroobj = { message: errorMessage };
        self.errors.push(erroobj);
    }

    function NoFilterDefined(Condition) {
        var s = "Find(): Funcao Filter() not implemented:";
        addError(s);
        Condition = null;
        throw new Error(s);
    }

    try {
        self.Filter = NoFilterDefined;

        self.Find = function () {
            debugger;
            var Condition = breeze.Predicate;
            var predicate;

            self.errors.removeAll();
            try {
                predicate = self.Filter(Condition);
            } catch (errorf) {
                var sf = "Find(): Error calling Filter() in {actionName}: {error}";
                sf = sf.replace("{error}", errorf.message);
                sf = sf.replace("{actionName}", predicate.toString());
                addError(sf);
                throw new Error(sf);
            }

            var query = breeze.EntityQuery
                .from(self.actionName)
                .where(predicate);

            try {
                debugger;
                var promisse = self.manager.executeQuery(query)
                    .then(querySucceeded)
                    .fail(queryFailed);

                // Here I suppose the .then(querySucceeded) already was called
            } catch (errore) {
                var se = "Find(): Erro calling query in {actionName}: {error}";
                se = se.replace("{error}", errore.message);
                se = se.replace("{actionName}", self.actionName);
                addError(se);
                throw new Error(se);
            }
        };

        self.FetchMetadata = function () {
            //self.manager.fetchMetadata() // not working?
            //   .fail(self.queryFailed);
            var query = breeze.EntityQuery
                    .from(actionName)
                    .where("1", "==", "0"); // Just to get metadata

            var execution = self.manager.executeQuery(query);
            execution.then(function (data) {
                data = null;
            });
            return true;
        };

        self.SetParameters = function (parameters) {
            self.parameter = ko.observable(parameters);
        };

        self.store = new breeze.MetadataStore(); // define metadataStore for all managers
        self.manager = new breeze.EntityManager({
            serviceName: self.serviceName,
            metadataStore: self.store
        });

    } catch (error) {
        var erroboj = { message: error.message };
        self.Errors.push(erroboj);
    }
}

try {
    // Uncomment //debugger to debug this script. Use Visual Studio an IE to debug.
    //debugger;

    var viewModel = new SearchViewModel("Api/Vehicle", "Vehicles");
    var parameter = {
        Id: "AAB-1113",
        Type: "CIF"
    };

    viewModel.SetParameters(parameter);

    viewModel.Filter = function (Condition) {
        "use strict";
        var self = this;
        var where = Condition.create("Type", "==", self.parameter.Type);

        if (parameter.Id !== null) {
            where = where.and("Id", "contains", self.parameter.Id);
        }

        return where;
    };

    ko.applyBindings(viewModel);

} catch (error) {
    alert("Erro de codigo:".concat(error.message));
}

最重要的问题是:为什么根本不调用
querysucceed
方法?我假设您的
queryFailed
也没有被调用?其中一个应该被击中

您是否已使用调试器验证两个方法都未调用?您确定有来自服务器的任何查询结果吗?我首先从网络流量日志中复制HTTP GET请求,然后在浏览器地址栏中重播它。只有在您确定服务器正在返回某些内容之后,我才能继续处理查询结果


注意:我刚刚在您的问题陈述下面看到了完整的ViewModel。

在看到完整的虚拟机之前,我写下了我的回复,几乎从头开始。但我保留了我最初的答案,因为知道如何解决一个谜很重要,而不仅仅是回答它

问题几乎可以肯定是你的谓词。如果删除
where(…)
子句,我敢打赌您会看到结果。我敢打赌,谓词设置的条件永远不会为真,因此您永远不会显示任何结果

self.Find中
将谓词初始化为Breeze
谓词
构造函数。我认为你永远都不想那样做。您可能需要创建一个新实例

你似乎想要创造一个“身份条件”——一个总是真实的条件。这对我来说似乎有点聪明。
NoFilterDefined
的实用性和实现对我来说也是一个谜。。。但现在我离手头的事情很远了

为什么不保持let
self.Filter()
保持
null
,直到出现实际的筛选条件?然后适当地构建查询,可能如下所示:

var query = breeze.EntityQuery.from(self.actionName); var predicate = self.Filter(); if (predicate) { query = query.where(predicate); } 如果您担心在查询方法返回之前会弄乱
data.results
数组(为什么?),可以先复制它

self.results(data.results.slice())

次要观点:

  • 我强烈建议将这些持久性关注点从ViewModel中移出,并作为一个助手组件,如
    dataservice
    datacontext
    as

  • 据我所知,您不需要任何
    fetchMetadata
    业务。Breeze在EntityManager的第一次查询时隐式获取元数据。您可以在必要时预取元数据(),但这里没有明显的必要

  • 您的
    self.Find
    方法是否应该将承诺返回给调用方

  • 为什么您的
    querysucceed
    返回
    true

  • 在执行查询之前,是否应清除
    self.Find
    中的
    self.results([])
    ?我通常这样做

  • 为什么
    queryFailed中的
    self.errors
    是一个可观察的问题。您正在将错误消息推送到错误消息数组中。。。在方法开头清除的数组。为什么是数组?为什么不能观察到一个简单的KO


最重要的问题是:为什么您的
查询成功了
方法根本没有被调用?我假设您的
queryFailed
也没有被调用?其中一个应该被击中

您是否已使用调试器验证两个方法都未调用?您确定有来自服务器的任何查询结果吗?我首先从网络流量日志中复制HTTP GET请求,然后在浏览器地址栏中重播它。只有在您确定服务器正在返回某些内容之后,我才能继续处理查询结果


注意:我刚刚在您的问题陈述下面看到了完整的ViewModel。

在看到完整的虚拟机之前,我写下了我的回复,几乎从头开始。但我保留了我最初的答案,因为知道如何解决一个谜很重要,而不仅仅是回答它

问题几乎可以肯定是你的谓词。如果删除
where(…)
子句,我敢打赌您会看到结果。我敢打赌,谓词设置的条件永远不会为真,因此您永远不会显示任何结果

self.Find中
将谓词初始化为Breeze
谓词
构造函数。我认为你永远都不想那样做。您可能需要创建一个新实例

你似乎想要创造一个“身份条件”——一个总是真实的条件。这对我来说似乎有点聪明。
NoFilterDefined
的实用性和实现对我来说也是一个谜。。。但现在我离手头的事情很远了

为什么不保持let
self.Filter()
保持
null
,直到出现实际的筛选条件?然后适当地构建查询,可能如下所示:

var query = breeze.EntityQuery.from(self.actionName); var predicate = self.Filter(); if (predicate) { query = query.where(predicate); } 如果您担心在查询方法返回之前会弄乱
data.results
数组(为什么?),可以先复制它

self.results(data.results.slice())

次要观点:

  • 我强烈建议将这些持久性关注点从ViewModel中移出,并作为一个助手组件,如
    dataservice
    datacontext
    as

  • 据我所知,您不需要任何
    fetchMetadata
    业务。Breeze隐式获取元数据 function querySucceeded(data) { self.results(data.results); };