在微风js查询完成后,使用基因敲除(knockout.js)applybindings [英] knockout.js applybindings after breeze js queries completed
问题描述
问题:如何构造代码,以便在执行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);
};
我想到了一些想法:
-
我很少一次将 observableArray 推入.太多的DOM更新.而是创建一个临时数组,并使用它更新 observableArray .我相信这是您要询问的性能问题的答案.
-
设置一个 initialize 方法,该方法将在所有初始异步加载方法完成后返回一个承诺.
-
延迟 ko.applyBindings 直到初始化承诺成功解决.
-
考虑在等待初始化完成时显示启动画面+微调器.
-
尝试在初始化期间不要做太多事情.
在这个答案中,我无法向您展示如何做所有这些事情.我将在此处显示#1,并向您推荐"在时获取在#2的文档中启动".网络搜索+实验是您其余的朋友.
用数组更新 observableArrayprocessBrokerQueryResults = 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: vm.muni is my ViewModel javascript file. Here's a method being exposed to exec a query: Here is the breeze query from dataservice.js file:
A few thoughts occur to me: 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. Set up an initialize method that returns a promise when all initial async load methods complete. Delay ko.applyBindings until the initialize promise resolves successfully. Consider showing a splashscreen + spinner while waiting for initialization to finish. 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.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);
});
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));
},
function getBrokers() {
var query = new entityModel.EntityQuery()
.from("GetBrokers")
//.orderBy("name");
return manager.executeQuery(query);
};
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屋!