Breezejs - 用于查询本地缓存的模式

时间:2013-04-03 16:42:38

标签: knockout.js breeze single-page-application

我有一个名为Item的类,它由PeriodId过滤。有很多时期 - 但我们只需要一次看一个。我想向用户显示初始数据加载(例如,PeriodId == 1)。然后,我希望用户能够在其他时段查询/过滤。

如果用户选择PeriodId == 2,我希望entityManager查询本地缓存,如果数据存在,则返回该数据。如果它不在本地缓存中,我希望它查询服务器,并将PeriodId == 2的集合添加到缓存中。如果用户然后单击PeriodId == 1,则该数据应该已经在缓存中而不是往返于服务器。

使用下面的代码,每次选择一个句点时,我都会点击服务器(即使我只是来回切换)。有没有解决这个问题的模式...我不知道这里的主键。

var getItems = function (myObservable, periodId, forceRemote) {

    var pId = periodId ? periodId : 1;

    var query = entityQuery.from('Item')
        .orderBy(orderBy.items)
        .where("PeriodId", "==", pId);

    if (!forceRemote) {
        var r = getLocal(query);
        if (r) {
            if (r.length > 3) {
                myObservable(r);
                return Q.resolve();
            }
        }
    }

    return manager.executeQuery(query)
        .then(querySucceeded)
        .fail(queryFailed);

    function querySucceeded(data) {
        if (myObservable) {
            myObservable(data.results);
        }
    }
};

function getLocal(query) {
    try {
        return manager.executeQueryLocally(query);
    } catch(e) {
        // set was not found in local cache, return null - forcing trip to server
        return null;
    }
}

更新:

结合Jay的建议,(我必须将'param'重命名为'pId','q'重命名为'query',如果forceRemote == true则重置queryParamCache,并且我必须在'breeze'前面添加FetchStrategy。) :

var queryParamCache = {};

var getItems = function(myObservable, periodId, forceRemote) {

    if (forceRemote) {
        queryParamCache = {};
    }

    var pId = periodId ? periodId : 1;

    var query = entityQuery.from('Item')
        .orderBy(orderBy.items)
        .where('PeriodId', '==', pId);

    var isInCache = queryParamCache[pId];

    if (isInCache && !forceRemote) {
        query = query.using(breeze.FetchStrategy.FromLocalCache);
    } else {
        queryParamCache[pId] = true;
        query = query.using(breeze.FetchStrategy.FromServer);
    }

    return manager.executeQuery(query)
        .then(querySucceeded)
        .fail(queryFailed);

    function querySucceeded(data) {
        rosterObservable(data.results);
    }
};

function queryFailed(error) {
    var msg = 'Error retreiving data. ' + error.message;
    logError(msg, error);
    throw error;
}

1 个答案:

答案 0 :(得分:6)

一个更简单的想法可能只是缓存关于您是否已执行查询的事实。而不是使用 executeQueryLocally 方法,在这种情况下,更容易使用指定 FetchStrategy 的功能。请注意,使用 FetchStrategy.FromLocalCache 时,您仍会收到一个承诺,但该承诺将立即执行。好的部分是您不必以不同方式处理远程与本地查询。

var queryParamCache = {};
var getItemsPromise = function (periodId, forceRemote) {

    var pId = periodId ? periodId : 1;

    var query = entityQuery.from('Item')
        .orderBy(orderBy.items)
        .where("PeriodId", "==", pId);


    var isInCache = queryParamCache[pId];
    if (isInCache && !forceRemote) {
        q = q.using(FetchStrategy.FromLocalCache);
    } else {
        queryParamCache[pId] = true;
        q = q.using(FetchStrategy.FromServer);
    }
    return  manager.executeQuery(q);
}

这种方法的另一个特点是它还处理“远程”查询不返回任何记录的情况。因此,与测试本地查询是否实际返回数据不同,当您还没有运行查询时,这将是假的,而当没有数据满足查询时,这种方法只是跟踪是否曾执行过查询,无论其结果如何。