缓存时同步获取数据,或者在不可用时获取异步数据

时间:2014-12-04 08:54:47

标签: angularjs deferred angular-promise

我有一个使用路由和视图的AngularJS应用。当加载特定视图并且控制器实例化时,我必须准备一些$scope模型数据。这些数据可以由附属服务提供,或者当服务没有时,我会进行异步调用以从服务器获取它。

当我最终获得这些数据时,我必须稍微更改一下,然后将其放在我的$scope上。

我认为这完全属于deferred / promise API。从服务获取数据是使用$resource服务实例完成的,并且已经是一个承诺。我唯一的问题是将同步代码转换为延迟/承诺模式。

问题

如何将我的同步代码处理更改为异步,以便我提供数据的函数始终返回一个承诺,在使用同步代码时会立即解决,并在一段时间后异步调用我的服务器?

所以过程:

  1. 尝试同步获取数据
  2. 如果同步失败,请将其设为异步
  3. 成功/失败
    1. 可用数据=>操纵它
    2. 数据不可用(无论哪种方式)=>重置状态
  4. 我尝试了什么

    var getData = function() {
        var defer = $q.defer();
    
        defer.promise
            .then(function () {
                // return cached item
                return dataCacheService.get("dataKey");
            })
            .then(function(data) {
                // cache returned data?
                if (!data)
                {
                    // no? get it from server returning a promise
                    return dataResource.get({
                        set: "models",
                        id: $routeParams.id
                    });
                }
            })
            .then(function (data) {
                // server returned data?
                if (!!data) // <= PROBLEM!!! This is not null, but is a Resource with unresolved promise?
                {
                    // yes? fine. manipulate it
                    delete data.details;
                    delete data.type.description;
    
                    $scope.lists.set(data.type);
    
                    return data;
                }
                // no data. sorry...
                $scope.resetType();
            })
            // something went wrong
            .catch($scope.resetType);
    
        // initiate deferred execution
        defer.resolve();
    
        return defer.promise;
    }
    
    ...
    
    $scope.model = {
        item: getData()
    };
    

1 个答案:

答案 0 :(得分:3)

您可以使您的服务始终返回承诺,如果数据可用,它将在REST调用后立即返回承诺。例如,您的服务可能如下所示:

var dataThatMayOrMayNotBeAvailable=null;

var getDataThatMayOrMayNotBeAvailable=function(){
   var deferred = $q.defer();
   if(dataThatMayOrMayNotBeAvailable){
       deferred.resolve(dataThatMayOrMayNotBeAvailable);
    }else{
     $http({...}).success(function(data){
       dataThatMayOrMayNotBeAvailable=data;
       deferred.resolve(data);
      });
    }

return deferred.promise;

}

用法:

getDataThatMayOrMayNotBeAvailable().then(function(data){
   console.log(data);
})