具有多个getJSON请求的Knockout.js绑定

具有多个getJSON请求的Knockout.js绑定,knockout.js,getjson,Knockout.js,Getjson,我的示例正在运行,但我对ko.applyBindings()语句的位置感到困惑。我曾经通过一个getJSON请求填充我的ViewModel。但是假设我需要2个getJSON请求。我将“var viewModel=new MyViewModel();”移到了getJSON之外,但是ko.applyBinding()在两个getJSON方法中,我知道不应该有两个绑定到同一个VM。我尝试将ko.applyBinding()移动到getJSON下面,但没有任何效果。因此,我将ko.applyBindin

我的示例正在运行,但我对ko.applyBindings()语句的位置感到困惑。我曾经通过一个getJSON请求填充我的ViewModel。但是假设我需要2个getJSON请求。我将“var viewModel=new MyViewModel();”移到了getJSON之外,但是ko.applyBinding()在两个getJSON方法中,我知道不应该有两个绑定到同一个VM。我尝试将ko.applyBinding()移动到getJSON下面,但没有任何效果。因此,我将ko.applyBinding()放在一个getJSON方法中,并调用VM方法来设置另一个JSON调用中的变量。这似乎是可行的,但我担心如果JSON请求在不同的时间返回,是否存在可能导致问题的时间问题

var MyViewModel = function() {
    var self = this;
    self.types = ko.observableArray();
    self.states = ko.observableArray();
    self.loadStates = function (states){
        self.states = states;
    }
}
var viewModel = new MyViewModel();
$(function () {
    $.getJSON('json/typeArray.json', function(jTypes){
        viewModel.types = jTypes;
        ko.applyBindings(viewModel);
    });
    $.getJSON('json/stateArray.json', function(jStates){
        viewModel.loadStates(jStates);
        //ko.applyBindings(viewModel);
    });
});
我可以使用嵌套的JSON请求,但我更希望它们同时执行

为什么不能将ko.applyBindings(viewModel)移到这个脚本的底部?我试过了,但我的两个数组都没有填充

更新:是的,有时间问题。有时第二个“状态”数组会在UI中更新,有时则不会。这显然取决于首先返回哪个getJSON。所以我确实需要找到解决这个问题的办法

以下是创建viewModel后移动applyBindings的尝试,该操作无效(请参见注释):


请注意,在这个答案中,我明确地重新设计了轮子,以展示如何工作的基本概念。有一些库,包括您似乎已经在使用的库(jQuery),使这项任务变得更加简单和流畅

基本上,您希望运行
ko.applyBindings
,但只有在两个单独的异步请求完成后才能运行。这里有一种模式可以做到这一点:

var viewModel = new MyViewModel();

function tryApplyBindings() {
  if (viewModel.types().length > 0 &&
      viewModel.states().length > 0) {
    ko.applyBindings(viewModel);
  }
}

$(function () {
    $.getJSON('json/typeArray.json', function(jTypes){
        console.log("Setting types in viewModel: " + viewModel.name);
        viewModel.types = jTypes;
        tryApplyBindings();
    });
    $.getJSON('json/stateArray.json', function(jStates){
        console.log("Setting states in viewModel: " + viewModel.name);
        viewModel.loadStates(jStates);
        tryApplyBindings();
    });
});
然而,再一次:请注意,这重新发明了轮子。您可以使用jQuery的promise特性(例如,可能带有)来实现更优雅、更干练的承诺组合



作为脚注,你也可以直接考虑运行<代码> Apple Buffuests,并创建一个看起来也很好的空数组视图。然后,当承诺返回时,UI会自动更新。

问题是,您为可观察数组设置了新值,而不将新对象分配给绑定属性

而不是分配:

viewModel.types = jTypes;
我建议采用下列方法:

//viewModel.types(jTypes);
viewModel.types(["type a", 'type b', 'type c']);
我创建了一个示例(通过setTimeout模拟请求),启动时数组为空,“时间”在1秒内更新,“状态”在2秒内更新:

var MyViewModel=function(){
var self=这个;
self.name=“myViewModel”;
self.states=ko.observearray();
self.types=ko.observearray();
}
var viewModel=新的MyViewModel();
应用绑定(视图模型);
//$(函数(){
//$.getJSON('json/typeArray.json',函数(jTypes){
//viewModel.types(jTypes);
//    });
//$.getJSON('json/stateArray.json',函数(jStates){
//viewModel.states(jStates);
//    });
//});
//$.getJSON('json/typeArray.json',函数(jTypes){
setTimeout(函数(){
viewModel.types([“a型”、“b型”、“c型])
}, 1000);
//$.getJSON('json/stateArray.json',函数(jStates){
setTimeout(函数(){
状态([“状态d”,“状态e”,“状态f']))
}, 2000);
//更多-在5秒内再次更新类型
//$.getJSON('json/typeArray.json',函数(jTypes){
setTimeout(函数(){
viewModel.types([“g型”、“h型”、“i型”、“j型])
},5000);

国家:
暂时没有状态。。。
类型:
暂时没有类型。。。

applyBindings应该调用一次,例如在viewModel创建之后立即调用。您应该在get json done函数中更新可观察属性:viewModel.types(jTypes)-我假设jTypes是一个数组。我尝试在viewModel创建之后放置applyBindings,但数组在HTML页面上从未得到更新。当我取消对getJSON中的applyBindings的注释时,它工作正常。请注意,console.log条目表明viewModel在所有情况下都得到了正确更新。除了t@TSV说,您可以使用
Promise.all()
来确保在调用回调之前加载所有json:这里的示例是一个ko示例,如果您使用我的建议(
Promise.all()
),您提到的争用问题就会得到解决不应该对ObservalArray造成问题-这就是我感到困惑的原因。但我正在重置对象,而新对象(jTypes)不可观察。我需要设置当前对象的值,但我不知道怎么做。用viewModel.types(jTypes)替换=完成了任务。“承诺”当您需要等待请求完成时,这项技术非常有用,但这里的情况并非如此。感谢您提供了正确的解决方案和正在运行的代码片段。
//viewModel.types(jTypes);
viewModel.types(["type a", 'type b', 'type c']);