【问题标题】:$.getJSON can't be passed into knockout observableArray$.getJSON 不能传入淘汰 observableArray
【发布时间】:2013-04-09 08:33:22
【问题描述】:

我正在尝试调用返回 Json 的 Api。我正在尝试将此返回的数据放入一个淘汰赛可观察数组中。我的视图模型如下所示:

var adminData = $.getJSON("/api/administrators");
//console.log(adminData);

var viewModel = {
    administrators: ko.observableArray(adminData)
};

ko.applyBindings(viewModel);

请求通过,并且正在返回一个对象,其中包含 adminData 中的预期数据,但是当我尝试将其添加到 ko.observableArray 时,我在控制台中得到了这个:初始化可观察数组时传递的参数必须是一个数组.我不知道如何将这些数据放入数组中进行淘汰。

【问题讨论】:

    标签: javascript json knockout.js


    【解决方案1】:

    $.getJSON 异步。结果数据仅在回调中可用。它不能作为$.getJSON 的返回值,文档中从未提及返回值。

    $.getJSON("/api/administrators", null, function(adminData, status, xhr){
        var viewModel = {
            administrators: ko.observableArray(adminData)
        };  
        ko.applyBindings(viewModel); 
    });
    

    如果你需要进行单独的AJAX调用,你应该使用jQuery.whenWait until all jQuery Ajax requests are done?

    $.when($.ajax("/api/administrators"), $.ajax("api/roles")).done(function(resp1, resp2){        
        ko.applyBindings({
            administrators: ko.observableArray(resp1[0]),
            roles: ko.observableArray(resp2[0]);
        }); 
    });
    

    这里有一些不太理想的解决方案,但它向您展示了幕后发生的事情。

    如果您不介意请求相互等待

    $.getJSON("/api/administrators", null, function(adminData){
        $.getJSON("/api/administrators", null, function(apiRoles){
            ko.applyBindings({
                administrators: ko.observableArray(adminData),
                roles: ko.observableArray(apiRoles);
            }); 
        });
    });
    

    如果你在乎,那就更复杂了,因为你需要跟踪请求是否完成

    var ajaxAdminData, ajaxApiRoles
    $.getJSON("/api/administrators", null, function(adminData, status, xhr){
        var ajaxAdminData = adminData;
        // If the other call finished, apply the bindings
        if (ajaxApiRoles) {
            applyBindings();
        }
    });
    
    $.getJSON("/api/administrators", null, function(apiRoles, status, xhr){
        ajaxApiRoles = apiRoles;
        // If the other call finished, apply the bindings
        if (ajaxAdminData) {
            applyBindings();
        }
    });
    
    function applyBindings() {
        ko.applyBindings({
            administrators: ko.observableArray(ajaxAdminData),
            roles: ko.observableArray(ajaxApiRoles);
        }); 
    }
    

    【讨论】:

    • 如果您只调用一次$.getJSON,但如果您想将$.getJSON 块放入计时器中(例如,在服务器的数据更改)您将遇到一些大问题,因为每次调用$.getJSON 时都会应用绑定。在这种情况下,最好将模型和绑定调用保留在 JSON 检索代码之外。只需使用一个全局数组来存储 JSON。
    • @Zac 建议将全局变量作为一种方法是一种廉价的出路。我相信你可以在不求助于全局变量的情况下弄清楚如何做到这一点。
    【解决方案2】:

    因为getJSON() 是异步的!您不能将其视为同步方法。看看那个 console.log 行是什么,它会显示它失败的原因。

    使用回调

    $.getJSON("/api/administrators", function(adminData) {
    
        var viewModel = {
            administrators: ko.observableArray(adminData)
        };
    
        ko.applyBindings(viewModel);
    }
    

    【讨论】:

    • 如果您想使用这种语法添加两个模型怎么办?例如,我还想调用 /api/roles,并将其添加到模型和 observableArray。
    • @rross 最简单的方法是从回调中进行第二次 AJAX 调用。如果要同时发送它们,则需要在两个处理程序之间共享变量,并且两个处理程序都需要确保两个调用都返回...稍后查看我的更新答案
    【解决方案3】:

    在您的 $.getJSON 回调中,只需更新您的可观察数组,然后在该数组上调用 valueHasMutated(),如:administrators.valueHasMutated()

    【讨论】:

      猜你喜欢
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-28
      • 2019-12-14
      • 2014-03-29
      • 2012-10-21
      • 1970-01-01
      相关资源
      最近更新 更多