在breeze js查询完成后,knockout.js applybindings

时间:2012-11-28 18:37:29

标签: knockout.js breeze

问题:如何构建我的代码,以便在执行ViewModel的所有查询之前不应用knockout绑定?

更新:经过一些进一步的研究和实验后,我认为使用延迟功能的内容可能会有效。我已经尝试了一些实现,但是它只会在调用查询之前推迟,而不是直到所有查询结果都被处理完毕。我显然在这里做错了,但我的javascript foo很弱。

使用的技术:实体框架5 w / Oracle,.Net 4 Web API,Knockout 2.2,Breeze 0.71.3

情况: Breeze用于调用Web API方法,该方法检索可枚举的POCO,填充可拆卸的可观察数组,并将数组绑定到View中的选择控件。 / p>

问题:在将ViewModel绑定应用于View之前,尚未完成breeze查询并且尚未填充knockout observable。返回查询结果时,UI将在5-7秒内无响应,同时填充ko observable,从而更新选择控件。 基于记录,这似乎是问题...

cshtml文件:

<select data-bind="options: $root.brokers, value: 'id', optionsText: 'name'">
<script data-main="/BrokerCommission/Scripts/app/main" src="/BrokerCommission/Scripts/require.js"></script>

main.js:

requirejs.config(
    {
        // well-know paths to selected scripts
        paths: {
            'breeze': '../breeze.debug', // debug version of breeze
            'text': '../text'// html loader plugin; see http://requirejs.org/docs/api.html#text
        }
    }
);

define(['logger', 'text', 'breeze'], function(logger) {

require(['vm.muni'],
function()
{
    logger.info('applying bindings');
    ko.applyBindings(my.vm);
});

vm.muni是我的ViewModel javascript文件。这是一个暴露给执行查询的方法:

getAllBrokers = function () {
        dataservice.getBrokers()
            .then(processBrokerQueryResults)
            .fail(handleQueryErrors);
    },

    processBrokerQueryResults = function (data) {
        logger.info("Start loading Brokers " + Math.round(new Date().getTime() / 1000));
        my.vm.brokers([]);
        $.each(data.results, function (i, d) {
            brokers.push(new my.Broker()
                .id(d.id)
                .name(d.name)
            );
        });
        logger.info("End loading Brokers " + Math.round(new Date().getTime() / 1000));
    },

以下是dataservice.js文件中的breeze查询:

function getBrokers() {
    var query = new entityModel.EntityQuery()
            .from("GetBrokers")
            //.orderBy("name");
    return manager.executeQuery(query);
};

1 个答案:

答案 0 :(得分:5)

我想到了一些想法:

  1. 很少逐一推入 observableArray 。 DOM更新太多。改为创建一个临时数组并用它更新 observableArray 。我相信这是你要问的性能问题的答案。

  2. 设置 initialize 方法,该方法在所有初始异步加载方法完成后返回承诺。

  3. 延迟 ko.applyBindings ,直到 initialize 承诺成功解决。

  4. 在等待初始化完成时,请考虑显示启动画面+微调器。

  5. 在初始化过程中尽量不要做太多。

  6. 在这个答案中,我无法告诉你如何做这些事情。我将在这里向您展示#1并在#2的文档中引用“Fetch on Launch”。网络搜索+实验是你的朋友。

    使用数组更新 observableArray
    processBrokerQueryResults = function (data) {
            ...
            var tempArray = []
            $.each(data.results, function (i, d) {
                tempArray.push(dtoToBroker(d));
            });
            brokers(tempArray);
            ...
    
            // I prefer named fns to long lambdas
            function dtoToBroker(dto) {
               return new my.Broker()
                      .id(d.id)
                      .name(d.name);
            }
    

    我喜欢使用ECMAScript 5 Array.map语法,该函数在将函数应用于源数组的每个元素后返回一个数组。所以我写道:

    processBrokerQueryResults = function (data) {
            ...
            brokers(data.results.map(dtoToBroker));
            ...
    }