bri*_*n s 6 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,填充knockout可观察数组,并且数组绑定到View中的select控件.
问题: 在将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>
Run Code Online (Sandbox Code Playgroud)
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);
});
Run Code Online (Sandbox Code Playgroud)
vm.muni是我的ViewModel javascript文件.这是一个暴露给exec查询的方法:
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));
},
Run Code Online (Sandbox Code Playgroud)
以下是dataservice.js文件中的breeze查询:
function getBrokers() {
var query = new entityModel.EntityQuery()
.from("GetBrokers")
//.orderBy("name");
return manager.executeQuery(query);
};
Run Code Online (Sandbox Code Playgroud)
我想到了一些想法:
我很少一个接一个地进入observableArray.DOM更新太多.改为创建一个临时数组并用它更新observableArray.我相信这是你所询问的性能问题的答案.
设置initialize方法,在所有初始异步加载方法完成时返回promise.
延迟ko.applyBindings直到initialize promise成功解析.
考虑在等待初始化完成时显示splashscreen + spinner.
在初始化期间尽量不要做太多.
我不能告诉你如何在这个答案中做每一件事.我将在这里向您展示#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));
...
}