Jquery 击退延迟加载和循环

Jquery 击退延迟加载和循环,jquery,json,knockout.js,lazy-loading,Jquery,Json,Knockout.js,Lazy Loading,我正试图构建一个树状结构,其中包含一个主json调用,该调用获取一个研究列表。由此,它在另一个json调用中使用studyId。此查询并不总是包含数据。如何处理未定义的?然而,这可能不是我的主要问题,因为我一直无法让它正常工作。我会一直关注这篇文章,所以请随意提问,我会尽快回复。谢谢 //=====================================================\ function StudyInfo(data) { this.StudyId = ko.o

我正试图构建一个树状结构,其中包含一个主json调用,该调用获取一个研究列表。由此,它在另一个json调用中使用studyId。此查询并不总是包含数据。如何处理未定义的?然而,这可能不是我的主要问题,因为我一直无法让它正常工作。我会一直关注这篇文章,所以请随意提问,我会尽快回复。谢谢

//=====================================================\

function StudyInfo(data) {
    this.StudyId = ko.observable(data.StudyId);
    this.Name = ko.observable(data.Name);
    this.Title = ko.observable(data.Title);
    this.Samples = ko.observableArray([]); // this field is not mapped in lazy load.
}
function SampleInfo(data) {
    this.Name = ko.observable(data.Name);
}

function viewModel() {
    var self = this;
    self.Studies = ko.observableArray([]);

    var request = $.getJSON("/api/studies");
    request.done(function (data) {
        var mappedStudies = $.map(data, function (item) {
            // now get study
            var study = new StudyInfo(item);
            study.Samples(self.getSamples(study.StudyId));
            return study;
        });
        self.Studies(mappedStudies);
    });
    request.fail(function (data) {
        // error stuff not important in example
    });
    self.getSamples = function (StudyId) {
        var request = $.getJSON("/api/samples/"+StudyId());
        request.done(function (data) {
            var mappedSamples = $.map(data, function (item) {
                var sample = new SampleInfo(item);
                return sample;
            });
            return mappedSamples;
        });
        request.fail(function (data) {
            // error stuff
        });
    };
}
<!--- list that resembles a tree -->
<ul data-bind="foreach: Studies()">
     <li><a><span data-bind="text: Name"></span></a>
          <ul data-bind="foreach: Samples">
                <li><a><span data-bind="Title"></span></a>
          </ul>
     </li>
<ul>
//=====================================================\

function StudyInfo(data) {
    this.StudyId = ko.observable(data.StudyId);
    this.Name = ko.observable(data.Name);
    this.Title = ko.observable(data.Title);
    this.Samples = ko.observableArray([]); // this field is not mapped in lazy load.
}
function SampleInfo(data) {
    this.Name = ko.observable(data.Name);
}

function viewModel() {
    var self = this;
    self.Studies = ko.observableArray([]);

    var request = $.getJSON("/api/studies");
    request.done(function (data) {
        var mappedStudies = $.map(data, function (item) {
            // now get study
            var study = new StudyInfo(item);
            study.Samples(self.getSamples(study.StudyId));
            return study;
        });
        self.Studies(mappedStudies);
    });
    request.fail(function (data) {
        // error stuff not important in example
    });
    self.getSamples = function (StudyId) {
        var request = $.getJSON("/api/samples/"+StudyId());
        request.done(function (data) {
            var mappedSamples = $.map(data, function (item) {
                var sample = new SampleInfo(item);
                return sample;
            });
            return mappedSamples;
        });
        request.fail(function (data) {
            // error stuff
        });
    };
}
<!--- list that resembles a tree -->
<ul data-bind="foreach: Studies()">
     <li><a><span data-bind="text: Name"></span></a>
          <ul data-bind="foreach: Samples">
                <li><a><span data-bind="Title"></span></a>
          </ul>
     </li>
<ul>


//=======================================================\

根据antishok的评论,为您的viewmodel尝试以下操作:

function StudyInfo(data) {
    this.StudyId = ko.observable(data.StudyId);
    this.Name = ko.observable(data.Name);
    this.Title = ko.observable(data.Title);
    this.Samples = ko.observableArray([]); // this field is not mapped in lazy load.
}
function SampleInfo(data) {
    this.Name = ko.observable(data.Name);
}

function viewModel() {
    var self = this;
    self.Studies = ko.observableArray([]);

    var request = $.getJSON("/api/studies");
    request.done(function (data) {
        var mappedStudies = $.map(data, function (item) {
            // now get study
            var study = new StudyInfo(item);
            study.Samples(self.getSamples(study.StudyId));
            return study;
        });
        self.Studies(mappedStudies);
    });
    request.fail(function (data) {
        // error stuff not important in example
    });
    self.getSamples = function (StudyId) {
        var request = $.getJSON("/api/samples/"+StudyId());
        request.done(function (data) {
            var mappedSamples = $.map(data, function (item) {
                var sample = new SampleInfo(item);
                return sample;
            });
            return mappedSamples;
        });
        request.fail(function (data) {
            // error stuff
        });
    };
}
<!--- list that resembles a tree -->
<ul data-bind="foreach: Studies()">
     <li><a><span data-bind="text: Name"></span></a>
          <ul data-bind="foreach: Samples">
                <li><a><span data-bind="Title"></span></a>
          </ul>
     </li>
<ul>
function viewModel() {
  var self = this;
  self.Studies = ko.observableArray([]);

  $.getJSON("/api/studies", function(allStudiesData) {

    $.each(allStudiesData, function (index, studyData) {

        var study = new StudyInfo(studyData);

        // The getJSON call returns immediately and the $.each loop will
        // loop around to the next study in allStudiesData.  Later on, 
        // each time the web server returns data to us from each of the samples
        // calls, the function(allSamplesData) will be called
        $.getJSON("/api/samples/"+studyData.StudyId, function(allSamplesData) {

            var mappedSamples = $.map(allSamplesData, function (sampleData) {
                var sample = new SampleInfo(sampleData);
                return sample;
            });
            study.Samples(mappedSamples);

            // If you put this push call outside the $.getJSON, the push would
            // happen before the mappedSamples were added to the study
            self.Studies.push(study);                    
        });                

    });

  });

  return self;
}

然而,我建议采取不同的办法。我建议将所有这些数据放在服务器上,这样您就可以对/api/studieswithsamples进行一次调用,并获得一大块JSON。这样,您的代码就可以简化,但真正的好处是,只需要对服务器进行一次HTTP调用就可以收回所有代码。这有助于缩短页面加载时间


注意:别忘了从viewmodel返回self。

根据antishok的评论,为您的viewmodel尝试以下操作:

function viewModel() {
  var self = this;
  self.Studies = ko.observableArray([]);

  $.getJSON("/api/studies", function(allStudiesData) {

    $.each(allStudiesData, function (index, studyData) {

        var study = new StudyInfo(studyData);

        // The getJSON call returns immediately and the $.each loop will
        // loop around to the next study in allStudiesData.  Later on, 
        // each time the web server returns data to us from each of the samples
        // calls, the function(allSamplesData) will be called
        $.getJSON("/api/samples/"+studyData.StudyId, function(allSamplesData) {

            var mappedSamples = $.map(allSamplesData, function (sampleData) {
                var sample = new SampleInfo(sampleData);
                return sample;
            });
            study.Samples(mappedSamples);

            // If you put this push call outside the $.getJSON, the push would
            // happen before the mappedSamples were added to the study
            self.Studies.push(study);                    
        });                

    });

  });

  return self;
}

然而,我建议采取不同的办法。我建议将所有这些数据放在服务器上,这样您就可以对/api/studieswithsamples进行一次调用,并获得一大块JSON。这样,您的代码就可以简化,但真正的好处是,只需要对服务器进行一次HTTP调用就可以收回所有代码。这有助于缩短页面加载时间


另外,别忘了从viewmodel返回self。

这里不清楚你在问什么。您是否在问如何处理getSamples调用中返回的未定义值?这是对AJAX异步本质的典型误解。问题出在
self.getSamples
中,您从ajax done回调函数内部
返回mappedSamples
,但您错误地认为它将返回此值作为
self.getSamples
的返回值。但是对self.getSamples的调用早在ajax完成回调触发之前就已经返回了(而且因为没有显式的
return
语句,它返回的是未定义的)。明天我必须阅读ajax,谢谢!不清楚你在问什么。您是否在问如何处理getSamples调用中返回的未定义值?这是对AJAX异步本质的典型误解。问题出在
self.getSamples
中,您从ajax done回调函数内部
返回mappedSamples
,但您错误地认为它将返回此值作为
self.getSamples
的返回值。但是对self.getSamples的调用早在ajax完成回调触发之前就已经返回了(而且因为没有显式的
return
语句,它返回的是未定义的)。明天我必须阅读ajax,谢谢!谢谢你的例子,现在更有意义了。我会考虑重新接电话。非常感谢!谢谢你的例子,现在更有意义了。我会考虑重新接电话。非常感谢!