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

Kev*_*vin 6 knockout.js single-page-application breeze

我有一个名为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;
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:

结合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;
}
Run Code Online (Sandbox Code Playgroud)

Jay*_*and 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);
}
Run Code Online (Sandbox Code Playgroud)

此方法的另一个特性是它还处理"远程"查询不返回任何记录的情况.因此,与测试本地查询是否实际返回数据不同,当您尚未运行查询时以及当没有数据满足查询时这将是假,此方法只是跟踪您是否曾执行过查询,不管其结果如何.