6

我有一个由 PeriodId 过滤的名为 Item 的类。有很多时期——但我们一次只需要看一个。我想向用户展示初始数据加载(比如 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,并且我必须在 FetchStrategy 前面加上 'breeze。'):

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;
}
4

1 回答 1

6

一个更简单的想法可能只是缓存您是否已执行查询的事实。而不是使用executeQueryLocally方法,在这种情况下,使用指定FetchStrategy的能力更容易。请注意,在使用 FetchStrategy.FromLocalCache时,您仍然会返回一个 Promise,但该 Promise 实际上会立即执行。好的部分是您不必区别对待远程和本地查询。

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);
}

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

于 2013-04-03T17:50:40.307 回答