Knockout:异步调用在ko.applyBindings()之前未完成.这是最好也是最简单的做法

Knockout : Async call not finished before ko.applyBindings(). Best, and easiest practice ?

本文关键字:最简单 未完成 调用 异步 ko applyBindings Knockout      更新时间:2023-09-26

我知道这个问题可能以前在这里被问过,但我似乎无法获得任何"最佳实践"。。作为一个新手,我可以用一种容易理解的方式。。。

淘汰码

$(document).ready(function() {
function viewModel() {
    var self = this;
    self.contacts = ko.observableArray();
        $.ajax({
            type: "POST",
            url: "ClubWebServices.asmx/GetContacts",
            data: "{'abc':'" + 123 + "'}", // if ur method take parameters
            contentType: "application/json; charset=utf-8",
            success: function (data) {
                var contactData = data.d;
                console.log("Nr 1: " + contactData);
                self.contacts(contactData);
                console.table(self.contacts());
            },
            dataType: "json",
            failure: function(error) {
                console.log(error);
            }
        });
    console.table("Nr 2: " + self.contacts());
    ko.applyBindings(new viewModel());
}

结果是在console.log Nr 1.之前调用了console.log Nr 2

所以。。如何在不创建层次结构的情况下解决这个问题?在层次结构中,我必须实现使用OnSuccess和onFailure事件的DataService层?

以下是一些想法。

  1. 您正试图从函数的声明中创建viewModel的实例,这可能会导致ko绑定出现问题
  2. 另一个注意事项是,在成功回调中对self的引用可能不是你想象的那样。使用调试器可以让你清楚地了解这一点

我会尝试重新安排一些类似的东西:

$(document).ready(function() {
  var viewModel = function (contactData) {
    var self = this;
    self.contacts = ko.observableArray(contactData);
  }
  $.ajax({
    type: "POST",
    url: "ClubWebServices.asmx/GetContacts",
    data: "{'abc':'" + 123 + "'}", // if ur method take parameters
    contentType: "application/json; charset=utf-8",
    success: function (data) {
      var contactData = data.d;
      console.log("Nr 1: " + contactData);
      ko.applyBindings(new viewModel(contactData));
    },
    dataType: "json",
    failure: function(error) {
      console.log(error);
    }
  });  
}

更改:我在ajax请求之前关闭您的viewModel声明,并将contactData传递给新的viewModel构造函数。

此外,创建一个jsfiddle将极大地帮助查找错误的原因。

我认为您的代码没有任何问题。

  • 在ViewModel构造函数中,您可以将模型绑定到DOM

  • 在服务回调之后,将数据添加到observableArray,然后ko将更新绑定DOM。

如果您希望在self.contacts填充后调用您的"Nr 2"表,请订阅:

var initialized = self.contacts.subscribe(function (newValue) {
    console.table("Nr 2: " + self.contacts()); // could use newValue instead
    initialized.dispose();
});

dispose调用防止在将来的更新中再次发生这种情况。或者你想让它,我不知道。

哦,正如JulianSolo所指出的,不要在视图模型创建函数中调用applyBindings。