2

我想在我的应用程序中实现“智能”缓存。我想总是首先从缓存中返回数据(如果没有可用的空对象/数组返回),然后总是从服务器获取数据并用更新的服务器响应替换缓存的响应。目标是始终快速向用户显示某些内容。我想以“角度”的方式来做,即 - 遵守承诺范式。

我找到了一个使用 $resource 服务的解决方案(http://www.bennadel.com/blog/2432-Applying-A-Cached-Response-To-An-AngularJS-Resource.htm),但是 $resource 非常糟糕如果您不只使用它提供的 4-5 个默认 REST 方法。它的自定义方法功能严重缺乏。我真的很想使用低级别的 $http 服务,因为它可以让我更好地控制我的请求,同时让我的控制器忘记整个缓存功能(即 - 避免先从控制器本身的缓存中获取数据,然后查询服务)。

有没有人处理过这个问题并有更好的解决方案?

谢谢 :-)

4

1 回答 1

1

http://jsfiddle.net/G23h7/

我创建了两个服务来完成我认为你想要完成的事情。第一个提供核心功能来接收一个承诺和一个对象(或数组),并在承诺解决时更新所述对象或数组。有一个 GUI 供您使用。

第二个服务将其集成到$http. 基本上你可以做smartHttp.forArray(config)smartHttp.forObj(config)代替$http(config). 如果您最终使用它并想要使用$http快捷方法,那么这应该很容易实现。这是未经测试的 - 所以将其视为伪代码。如果您立即返回缓存值/无效值,那么使用承诺作为服务的返回值并没有真正意义smartHttp(除非您试图使服务与 可互换$http)。如果你希望它成为一个承诺或任何你可以改变的原因:

var general = function (obj, methodName) {
    // ...
    return obj;
};

到以下:

var general = function (obj, methodName) {
    // ...
    return $q.when(obj);
};

当然,然后要求提供$q服务。这里真正的问题是请求之间的平等——我认为$http这很好;我做了一个天真的键——你可能想改变它(只要你有简单的请求/对我认为不重要的所有东西都有相同的顺序)。

myApp.factory('smartCache', function () {
    var service = {};

    service.forArray = function (array, promise, clear) {
        promise.then(function (promiseResult) {
            if (clear) {
                array.length = 0;
            }

            angular.forEach(promiseResult, function (promiseResultElement) {
                array.push(promiseResultElement);
            });
        });
    };

    service.forObj = function (obj, promise, clear) {
        promise.then(function (promiseResult) {
            if (clear) {
                for (var prop in obj) {
                    delete obj[prop];
                }           
            }

            for (var prop in promiseResult) {
                obj[prop] = promiseResult[prop];
            }
        });
    };

    return service;
});

myApp.factory('smartHttp', function ($http, smartCache, $cacheFactory) {   
    var cache = $cacheFactory('smartHttp');

    var service = {};

    var general = function (config, methodName, initialValue) {
        var obj;
        var key = JSON.stringify([ config.url, config.method, config.params, config.data ]);
        var cachedObj = cache.get(key);
        if (cachedObj !== undefined) {
            obj = cachedObj;
        } else {
            obj  = initialValue;
        }

        var promise = $http(config);
        var smartCachePromise = promise.then(function (result) {
            return result.data;
        });
        smartCache[methodName](obj, smartCachePromise, true);

        return obj;
    };

    service.forObj = function (config) {
        return general(config, 'forObj', {});
    }

    service.forArray = function (config) {
        return general(config, 'forArray', []);
    }


    return service;
});
于 2013-09-02T02:49:21.533 回答