【问题标题】:Defer async computed observable推迟异步计算的 observable
【发布时间】:2023-03-18 07:55:01
【问题描述】:

我一直在疯狂地试图弄清楚这一点。当异步调用完成时,我已经看到了很多在 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
};

这是 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(如果有帮助)

【问题讨论】:

    标签: javascript jquery knockout.js knockout-2.0


    【解决方案1】:

    你的read回调全错了。

    回调:

    function (data) {
        return data;
    }
    

    是死代码,它会将数据返回给调用此回调的 jQuery 函数,它不会对它做任何事情。

    你需要返回 deferred 本身:

    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);
            });
        });
    

    【讨论】:

    • 如此接近。我想知道async 是否是内置扩展器。我在ko.extenders 中找不到它,在线文档几乎为零。也就是说......它仍然只是将承诺对象返回给skills
    • 啊,原来如此。抱歉,我在回答这个问题时做了一场噩梦……感谢您的耐心等待。将再次更新。
    • 别担心,我非常感谢您的帮助。你会得到一张“正确”的支票:-)
    猜你喜欢
    • 1970-01-01
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 2014-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多