Breezejs — шаблон для запроса локального кеша

У меня есть класс 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;
    }
}

ОБНОВЛЕНИЕ:

Включая предложение Джея (мне пришлось переименовать 'param' в 'pId', 'q' в 'query', сбросить queryParamCache, если forceRemote==true, и мне пришлось добавить 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;
}

person Kevin    schedule 03.04.2013    source источник


Ответы (1)


Более простой идеей может быть просто кэширование факта того, выполнили ли вы запрос или нет. И вместо использования метода 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);
}

Другая особенность этого подхода заключается в том, что он также работает со случаем, когда «удаленный» запрос не возвращает никаких записей. Таким образом, в отличие от проверки того, действительно ли локальный запрос возвращает данные, которые будут ложными как тогда, когда вы еще не выполнили запрос, так и когда нет данных, удовлетворяющих запросу, этот подход просто отслеживает выполняли ли вы когда-либо запрос, независимо от его результатов.

person Jay Traband    schedule 03.04.2013
comment
Великолепно, Джей! Несколько настроек, и это сработало ... Я обновлю свой вопрос с внесенными изменениями. Спасибо! - person Kevin; 03.04.2013