我有许多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,任务或两者都已用某些内容更新,我会从等待上述情况发出回调...
答案 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);
};