等到KO.Observable已更新

时间:2014-01-18 17:27:24

标签: javascript knockout.js

我有许多ko.observable和ko.observableArray对象 - 其中一些可以是复杂/嵌套的,并且在我的一个应用程序的早期定义,但是由服务器准备好时推送的数据异步调用和填充。我的客户端有回调方法,它从服务器接收这些数据,然后在需要时填充各种KO对象。 (所有这些数据都通过信号器推送)。

我有许多用户输入表单,我需要确保在呈现表单之前存在数据。在主要情况下,这很安静,因为数据提前填充,并在一段时间后访问表单。

但是,当用户点击F5并刷新浏览器时会出现问题。现在必须再次请求后台数据并填充表单下拉列表,但各种数据项需要一秒左右才能被服务器发回。

因此,我需要能够延迟表单的填充,直到所有当前适用的可观察对象都已更新。

我写了一个对Knockout observableArray的扩展,如下所示:

ko.observableArray.fn.await = function (callback) {

    var items = this();
    var hasValue = false;
    function observe() {
        if (typeof items !== "undefined" && items !== null && typeof items.length !== "undefined") {
            for (var i = 0, len = items.length; i < len; i++) {
                hasValue = (items[i]._destroy !== true);
                if (hasValue) break;
            }
        }
        if (!hasValue) {
            setTimeout(observe, 80);
            return;
        }

        callback();
    }
    observe();
};

一个简单的例子说明了如何使用它:

var categories = ko.observableArray([]);

...
OpenFormClicked = function(e) {

    // delay if the data is not yet ready
    categories.await( function() {

         // any code that used category data

         // Now show the popup;
         popup.show();
    });
}

这很好用,我打算写一个类似的ko.observabley.fn.await,但后来我发现ko.subscribable.fn会是一个更好的选择,因为我只有一个扩展名KO在我的应用程序中。

然而,在这一点上,我不确定要检查什么。真的,我只是想知道是否已经填充了可订阅的内容,并且它的内容已经以某种方式更新了,这样它们就不是创建它的原始/默认值。

如果我定义这样的KO:

var userTaskData = ko.observable({
    id: ko.observable(),
    tasks: ko.observableArray([])
});

如果ID,任务或两者都已用某些内容更新,我会从等待上述情况发出回调...

1 个答案:

答案 0 :(得分:2)

最后我用两个包装类解决了这个问题。一个用于ko,observable,另一个用于ko.observableArray和JQuery承诺,我还编写了一个实用函数,允许等待多个延迟的KO ......

ko.deferredObservable = function (initValue) {
    var result = ko.observable(initValue);
    var dfd = new jQuery.Deferred();
    var promise = dfd.promise();
    result.subscribe(function (value) {
        dfd.resolve();
    });
    result.await = function (callback) {
        promise.then(callback);
    };
    result._promise = promise;
    return result;
};

ko.deferredObservableArray = function (initValue) {
    var result = ko.observableArray(initValue);
    var dfd = new jQuery.Deferred();
    var promise = dfd.promise();
    result.subscribe(function (value) {
        dfd.resolve();
    });
    result.await = function (callback) {
        promise.then(callback);
    };
    result._promise = promise;
    return result;
};

// Utility Extension for awaiting a defined KO or Array of KO's
ko.utils.await = function (arr, callback) {
    var promisesArray = ([].concat(arr)).map(function(item) { return item._promise; });
    var deff = $.when.apply($, promisesArray);
    deff.then(callback);
};