延迟异步计算的可观察量

EHo*_*ski 2 javascript jquery knockout-2.0 knockout.js

我一直在疯狂试图弄清楚这个.我已经看到很多混淆且难以实现的例子,当异步调用完成时在Knockout中填充计算的observable,但我似乎无法使用模块显示模式使其工作.

我正在尝试创建一个只读的observable,因为这就是我所需要的.如果我不需要匿名函数来运行来发出请求,我甚至不会创建一个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
};
Run Code Online (Sandbox Code Playgroud)

这是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>
Run Code Online (Sandbox Code Playgroud)

我想做的是创建skills变量,获取数据并返回它.数据已经以数组形式返回(例如:),[{Title: "ABC"}]但它似乎没有绑定.我尝试使用$.when().then()(因为我更喜欢),但即使计算值延迟,它仍然不会更新.

对我来说,真正复杂的部分是可变范围.模块显示模式在涉及范围时很糟糕.我已经绞尽脑汁待了3个小时......如果有人能指引我朝着正确的方向前进,我将不胜感激.

使用Knockout 3.1 编辑(如果有帮助)

Mic*_*Fry 6

你的read回调都是错的.

回调:

function (data) {
    return data;
}
Run Code Online (Sandbox Code Playgroud)

是死代码,它将数据返回到调用此回调的jQuery函数,该函数将不会执行任何操作.

您需要返回延迟本身:

read: function () {
    return $.get("http://horodyski.me/api/skills");
}
Run Code Online (Sandbox Code Playgroud)

你还需要这里的异步扩展器: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;
};
Run Code Online (Sandbox Code Playgroud)

使用如下:

var skills = ko.computed(...).extend({ async: null });
Run Code Online (Sandbox Code Playgroud)

如果要在传递给视图之前挂钩JSON:

var skillsJson = ko.computed(...).extend({ async: null });
var skills = ko.computed(function () {
    return transformData(skillsJson());
};
Run Code Online (Sandbox Code Playgroud)

要么:

var skills = ko.computed(function () {
        return $.get("url").then(function (data) {
            return transform(data);
        });
    });
Run Code Online (Sandbox Code Playgroud)