最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - wait for ajax result to bind knockout model - Stack Overflow

programmeradmin1浏览0评论

I have getGeneral function that calls ajax GET. When ajax recieves data (json), it creates KO model from given json and returns created KO.

When Knockout model is created and values are assigned, knockout applybindings should be called. Here is my code:

Defines GeneralModel and some related functions (inside "GeneralModel.js"):

var GeneralModel = function() {

   //for now it is empty as data ar binded automatically from json
   // CountryName is one of the properties that is returned with json
} 

function getGeneral(pid) {
    $.ajax({
        url: "/api/general",
        contentType: "text/json",
        dataType: "json",
        type: "GET",
        data: { id: pid},
        success: function (item) {
            var p = new GeneralModel();
            p = ko.mapping.fromJS(item);
            return p;
        },
        error: function (data) {

        }
    });    
}

This is called from another file (GeneralTabl.html), it should call get function and applyBindings to update UI:

var PortfolioGeneral = getGeneral("@Model.Id");
ko.applyBindings(PortfolioGeneral, document.getElementById("pv-portfolio-general-tab"));

However, in this scenario I am getting error (CountryName is not defined). This is because applyBindings happens before ajax returns data, so I am doing applyBindings to empty model with undefined properties.

Mapping from Json to Model happens here and is assignes values: p = ko.mapping.fromJS(item);

I can also fill in GeneralModel with all fields, but it is not necessary (I guess):

  var GeneralModel = function() {    
      CountryName = ko.observable();
      ...
  } 

It will still give an error "CountryName is not defined".

What is the solution?

1) Can I somehow move getGeneral inside GeneralModel, so get data would be part of GeneralModel initialization?

or

2) Maybe I should somehow do "wait for ajax results" and only then applyBindings?

or

I believe there are other options, I am just not so familiar with KO and pure JS.

Note: I fully understand that this is because Ajax is Async call, so the question is how to restructure this code taking into account that I have two seperate files and I need to call getGeneral from outside and it should return some variable.

I have getGeneral function that calls ajax GET. When ajax recieves data (json), it creates KO model from given json and returns created KO.

When Knockout model is created and values are assigned, knockout applybindings should be called. Here is my code:

Defines GeneralModel and some related functions (inside "GeneralModel.js"):

var GeneralModel = function() {

   //for now it is empty as data ar binded automatically from json
   // CountryName is one of the properties that is returned with json
} 

function getGeneral(pid) {
    $.ajax({
        url: "/api/general",
        contentType: "text/json",
        dataType: "json",
        type: "GET",
        data: { id: pid},
        success: function (item) {
            var p = new GeneralModel();
            p = ko.mapping.fromJS(item);
            return p;
        },
        error: function (data) {

        }
    });    
}

This is called from another file (GeneralTabl.html), it should call get function and applyBindings to update UI:

var PortfolioGeneral = getGeneral("@Model.Id");
ko.applyBindings(PortfolioGeneral, document.getElementById("pv-portfolio-general-tab"));

However, in this scenario I am getting error (CountryName is not defined). This is because applyBindings happens before ajax returns data, so I am doing applyBindings to empty model with undefined properties.

Mapping from Json to Model happens here and is assignes values: p = ko.mapping.fromJS(item);

I can also fill in GeneralModel with all fields, but it is not necessary (I guess):

  var GeneralModel = function() {    
      CountryName = ko.observable();
      ...
  } 

It will still give an error "CountryName is not defined".

What is the solution?

1) Can I somehow move getGeneral inside GeneralModel, so get data would be part of GeneralModel initialization?

or

2) Maybe I should somehow do "wait for ajax results" and only then applyBindings?

or

I believe there are other options, I am just not so familiar with KO and pure JS.

Note: I fully understand that this is because Ajax is Async call, so the question is how to restructure this code taking into account that I have two seperate files and I need to call getGeneral from outside and it should return some variable.

Share Improve this question edited Nov 21, 2013 at 13:16 renathy asked Nov 21, 2013 at 12:53 renathyrenathy 5,37520 gold badges92 silver badges155 bronze badges 5
  • possible duplicate of How to return the response from an AJAX call? – Rory McCrossan Commented Nov 21, 2013 at 12:53
  • Remember, the first A of AJAX means Asyncronous. Your getGeneral function has exited long before the AJAX call returns anything. – Rory McCrossan Commented Nov 21, 2013 at 12:54
  • Yes< I fully understand this, I am asking how to restructure it properly. – renathy Commented Nov 21, 2013 at 13:15
  • move applyBindings in the AJAX success function. Restructure you model so that you can do it this way. – Saturnix Commented Nov 21, 2013 at 13:20
  • I cannot move into ajax success as it is seperate file. – renathy Commented Nov 21, 2013 at 13:28
Add a ment  | 

1 Answer 1

Reset to default 5

Try using the returned promise interface:

function getGeneral(pid) {
    return $.ajax({
        url: "/api/general",
        contentType: "text/json",
        dataType: "json",
        type: "GET",
        data: {
            id: pid
        }
    });
}

getGeneral("@Model.Id").done(function (item) {
    var p = new GeneralModel();
    p = ko.mapping.fromJS(item);
    ko.applyBindings(p, document.getElementById("pv-portfolio-general-tab"));
}).fail(function () {
    //handle error here
});
发布评论

评论列表(0)

  1. 暂无评论