有时仅更新计算的observable

时间:2013-02-14 20:38:26

标签: ajax knockout.js

我有一个计算的observable,它根据其他数据(在计算的observable中)进行AJAX调用。结果数据用于填充UI的一部分。有时UI的那部分是隐藏的,我想在隐藏时避免使用AJAX。现在我有以下内容,但只要isVisible成为true

,它就会更新
this.loadData = ko.computed(function() {
    if (this.isVisible()) {
        this.isProcessing(true);
        var self = this;
        $.when.apply($, ko.utils.arrayMap(this.parent.data.filteredSelectedDatasetLinks(), function(datasetLink) {
            return $.ajax({
                url: datasetLink.getDownloadUrl('.json'),
                success: function(data) {
                    //... do stuff with the data
                }
            });
        }))
        .done(function() {
            self.isProcessing(false);
        });
    }
}, this);

所以显然我需要以某种方式将其拆分,但我还没弄明白该怎么做。重申一下,当isVisible为假时,不会发生更新。当isVisible为真时,只要filteredSelectedDatasetLinks发生更改,就会发生更新。当isVisible变为true时,如果filteredSelectedDatasetLinks在错误时更改,则会发生更新。

2 个答案:

答案 0 :(得分:0)

大概你想在filteredSelectedDatasetLinks改变时调用你的ajax(并且只有在可见的情况下?)。我认为最好的方法是使用subscribe函数明确表示依赖...(我已经略微简化并修复了最终'this'的问题)

this.filteredSelectedDatasetLinks.subscribe(function() {
    if (this.isVisible()) {
        this.isProcessing(true);
        var self = this;
        $.when.apply($, ko.utils.arrayMap(this.filteredSelectedDatasetLinks(), function(datasetLink) {
            return $.ajax({
                url: datasetLink.getDownloadUrl('.json'),
                success: function(data) {
                    //... do stuff with the data
                }
            });
        }))
        .done(function() {
            self.isProcessing(false);
        });
    }
}, this);

原始尝试的问题是ko.computed运行一次该函数并自动计算出需要订阅的哪些observable。在你的情况下,这包括isVisible observable(这不是你想要的)。但是直接使用subscribe调用明确表示你不再需要担心isVisible触发回调。

答案 1 :(得分:0)

以下是我根据RP Niemeyer的评论最终使用的内容。

this.trackData = ko.computed(function() {
    this.parent.data.filteredSelectedDatasetLinks();    // for notification
    this.isDataDirty(true);
}, this);

this.loadData = ko.computed(function() {
    if (this.isVisible() && this.isDataDirty()) {
        this.isDataDirty(false);
        this.isProcessing(true);
        var self = this;
        $.when.apply($, ko.utils.arrayMap(this.parent.data.filteredSelectedDatasetLinks.peek(), function(datasetLink) {
            return $.ajax({
                url: datasetLink.getDownloadUrl('.json'),
                success: function(data) {
                    //... do stuff with the data
                }
            });
        }))
        .done(function() {
            self.isProcessing(false);
        });
    }
}, this);