KnockoutJS和async ajax调用

时间:2014-08-04 02:02:14

标签: asynchronous knockout.js spservices

我使用SPServices和KnockoutJS在页面上加载一些数据,特别是项目列表和每个项目的任务数。

我稍微简化了示例,但我遇到的问题是获取ajax调用异步的值。我通过使用jQuery绑定结果而不是返回任何内容来廉价地解决它:

function ProjectModel(title, id) {
    var self = this;
    self.id = id;
        self.title = title;             
    self.tasks = ko.computed(function() {
              $().SPServices({
                operation: "GetListItems",
                async: true,
                webURL: "/projects/" + self.id,
                listName: "Tasks",
                CAMLQuery: // query..,              
                CAMLViewFields: "<ViewFields><FieldRef Name='ID' /></ViewFields>",
                completefunc: function (xData, Status) {
                        $(".tasks-" + id).text($(xData.responseXML).SPFilterNode("z:row").length);  
                        }
              });       
        });
}

我看了一下这些网站 Async dependantobservables async computed observables

这是要走的路吗? 编辑:

好了所以更多的代码(在这里删除了一些东西):

function onGetProjectsCompleted(projects) {
    var projectViewModel = new ProjectViewModel();
    projectViewModel.init(projects);
    ko.applyBindings(projectViewModel);
}

function beforeLoadingProjects() {
    $(".loadingMessage").show();
}

function initProjectsView() {
    ProjectsRepository.getOpenProjects(beforeLoadingProjects, onGetProjectsCompleted);
}

function ProjectViewModel() {
        var self = this;
        self.openProjects = ko.observableArray();       

        self.init = function initProjectViewModel(projects) {
            $.each(projects, function() {
                self.openProjects.push(this);
            });

            });
        };
    }


    var ProjectsRepository = {
        getOpenProjects: function (beforeComplete, onComplete) {
            var options = {
                operation: "GetListItems",
                completefunc: function(xData, status) {
                    var projects = new Array();
                    $(xData.responseXML).SPFilterNode("z:row").each(function() {
                        var item = $(this);
                        projects.push(new ProjectModel(
                            item.attr("ows_Title"), 
                            item.attr("ows_ProjectID")                      
                        ));
                    });
                    onComplete(projects);
                }
            };

            beforeComplete();
            $().SPServices(options);
        }
    };

请注意,我不想列出每个项目的任务,我只想拥有一个属性,其中包含每个项目的任务数,即没有数组。

再次感谢。

2 个答案:

答案 0 :(得分:1)

我无法告诉您如何使用上面的类(模型),但@anders是正确的:您的模型不应该直接操作DOM元素......这就是Knockout&#39;视图绑定用于...

试试这个(披露:我没有在现场环境中测试这个):

型号:

function ProjectModel(title, id) {
    var self = this;
    self.id = id;
    self.title = title;
    self.tasks = ko.observable(0);


    $().SPServices({
        operation: "GetListItems",
        async: true,
        webURL: "/projects/" + self.id,
        listName: "Tasks",
        CAMLQuery: // query..,              
        CAMLViewFields: "<ViewFields><FieldRef Name='ID' /></ViewFields>",
        completefunc: function (xData, Status) {

            if (Status !== "success") {
                alert("failed to get tasks! Ajax call error.");
                return;
            }

            self.tasks(
                $(xData.responseXML).SPFilterNode("rs:data").attr('ItemCount')
            );

        }
    });
}

查看:

<div id="mytemplate">
    <h2>
        <span data-bind="text: title"></span> Project has 
        <span data-bind="text: tasks"></span> Tasks
    </h2>
</div>

控制器/结合:

ko.applyBindings(
    new ProjectModel("your project title", "your project ID"),
    document.getElementById("mytemplate")
);

尝试使用上面的内容并查看是否获得输出...任务数量最初为零,但如果您的任务列表有效且任务在那里,那么一旦查询完成,它将自动更新。

答案 1 :(得分:0)

我之前没有使用过SPServices,但我首先要通过创建服务对象将模型与ajax调用分开。

然后传入observable来填充

这样的东西
var ajaxServices = (function(){
      return {
        getProjectTasks: getProjectTasks
      };
      function getProjectTasks(projectId, tasksObservable){
        $().SPServices({
          operation: "GetListItems",
          async: true,
          webURL: "/projects/" + projectId,
          listName: "Tasks",
          CAMLQuery: // query..,              
          CAMLViewFields: "<ViewFields><FieldRef Name='ID' /></ViewFields>",
          completefunc: function (xData, Status) {
          tasksObservable(xData);
        }); 
      }
    })();


function ProjectModel(title, id) {
  var self = this;
  self.id = id;
  self.title = title;             
  self.tasks = ko.observableArray([]);

  self.getTasks = function (){
    ajaxServices.getProjectsTasks(sif.id, self.tasks);
  };    
}