我一直疯狂地试图弄明白这个。我已经看到很多混淆且难以实现的例子,当异步调用完成时,在Knockout中填充计算的observable,但我似乎无法使用模块显示模式使其工作。
我试图创建一个只读的可观察对象,因为这就是我所需要的。如果我不需要匿名函数来运行来发出请求,我甚至不会制作一个可观察的内容。这是我的观点模型:
eh.vm.skills = function () {
//#region Public Variables
var skills = ko.computed({
read: function () {
$.get("http://horodyski.me/api/skills", function (data) {
return data;
});
},
deferEvaluation: true
}),
//#endregion
//#region Public Interface
return {
skills: skills
}
//#endregion
};
这是HTML绑定:
<ul class="skills skills-top" id="skills" data-bind="foreach: skills">
<li>
<i data-bind="text: $index"> </i>
<span data-bind="text: $data.Title"></span>
</li>
</ul>
<script src="//cdn.horodyski.me/js/vm.js"></script>
<script>
ko.applyBindings(eh.vm.skills, $("#skills")[0]);
</script>
我想做的是创建skills
变量,获取数据并将其返回。数据已经以数组形式返回(例如:[{Title: "ABC"}]
)但它似乎没有绑定。我尝试使用$.when().then()
代替(因为我更喜欢),但即使延迟计算值,它仍然无法更新。
对我来说,真正复杂的部分是变量范围。模块显示模式在涉及范围时很糟糕。我已经绞尽脑汁待了3个小时......如果有人能指引我朝着正确的方向前进,我们将不胜感激。
编辑使用Knockout 3.1(如果有帮助)
答案 0 :(得分:6)
你的read
回调都错了。
回调:
function (data) {
return data;
}
是死代码,它将数据返回到调用此回调的jQuery函数,该函数将对此无效。
您需要返回延迟本身:
read: function () {
return $.get("http://horodyski.me/api/skills");
}
您还需要这里的异步扩展程序:http://smellegantcode.wordpress.com/2012/12/10/asynchronous-computed-observables-in-knockout-js/
ko.extenders.async = function(computedDeferred, initialValue) {
var plainObservable = ko.observable(initialValue), currentDeferred;
plainObservable.inProgress = ko.observable(false);
ko.computed(function() {
if (currentDeferred) {
currentDeferred.reject();
currentDeferred = null;
}
var newDeferred = computedDeferred();
if (newDeferred && (typeof newDeferred.done == "function")) {
plainObservable.inProgress(true);
currentDeferred = $.Deferred().done(function(data) {
plainObservable.inProgress(false);
plainObservable(data);
});
newDeferred.done(currentDeferred.resolve);
} else {
plainObservable(newDeferred);
}
});
return plainObservable;
};
用过:
var skills = ko.computed(...).extend({ async: null });
如果要在传递给视图之前挂钩JSON:
var skillsJson = ko.computed(...).extend({ async: null });
var skills = ko.computed(function () {
return transformData(skillsJson());
};
或者:
var skills = ko.computed(function () {
return $.get("url").then(function (data) {
return transform(data);
});
});