在微风js查询完成后,使用基因敲除(knockout.js)applybindings [英] knockout.js applybindings after breeze js queries completed

查看:102
本文介绍了在微风js查询完成后,使用基因敲除(knockout.js)applybindings的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

更新:经过一些进一步的研究和实验,我认为使用类似于Deferred函数的方法可能有效.我已经尝试了一些实现,但是它仅推迟直到查询被调用,而不是直到所有查询结果都被处理为止.我显然在这里做错了,但是我的javascript foo很弱.

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

这种情况: Breeze被用于调用Web API方法,该方法检索可枚举的POCO,填充可剔除的可观察数组,并将该数组绑定到View中的select控件. /p>

问题:在将ViewModel绑定应用于View之前,微风查询尚未完成,并且没有填充可剔除的可观察对象.返回查询结果后,UI会在5到7秒钟内无响应,同时会填充ko可观察的对象,从而更新选择控件. 根据日志记录,这似乎是问题所在……

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文件的轻而易举的查询:

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

解决方案

我想到了一些想法:

  1. 很少一次将 observableArray 推入.太多的DOM更新.而是创建一个临时数组,并使用它更新 observableArray .我相信这是您要询问的性能问题的答案.

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

  3. 延迟 ko.applyBindings 直到初始化承诺成功解决.

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

  5. 尝试在初始化期间不要做太多事情.

在这个答案中,我无法向您展示如何做所有这些事情.我将在此处显示#1,并向您推荐"在时获取在#2的文档中启动".网络搜索+实验是您其余的朋友.

用数组更新 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

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 is my ViewModel javascript file. Here's a method being exposed to exec a query:

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));
    },

Here is the breeze query from dataservice.js file:

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

A few thoughts occur to me:

  1. I rarely push one-by-one into the observableArray. Too many DOM updates. Create a temporary array instead and update the observableArray with that. I believe this is the answer to the performance problem you're asking about.

  2. Set up an initialize method that returns a promise when all initial async load methods complete.

  3. Delay ko.applyBindings until the initialize promise resolves successfully.

  4. Consider showing a splashscreen + spinner while waiting for initialization to finish.

  5. Try not to do too much during initialization.

I can't show you how to do every one of these things in this answer. I'll show you #1 here and refer you "Fetch on Launch" in the documentation for #2. Web search + experimentation are your friends for the rest.

Update observableArray with an array

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);
        }

I like to use the ECMAScript 5 Array.map syntax which returns an array after applying a function to each element of a source array. So I'd write:

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

这篇关于在微风js查询完成后,使用基因敲除(knockout.js)applybindings的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆