2015-03-19 128 views
0

我正在尝试为http请求做一个缓存工厂,所以它不会使服务器为同一请求做很多工作。但似乎我使用推迟的“吞下”数据的方式,我不知道为什么。Angularjs Factory延迟的数据消失

控制台输出如下:

数据获取:
对象{状态: “OK”,数据:对象的errorMessage:空,异常:空}
成功
不确定

ImportFactory:

factory("importFactory", function ($http, $q, loggingService) { 
return{ 
    fetchedData: [], 
    cacheTransport: function (transportsId, data) { 
     this.fetchedData.push({"transportsId": transportsId, "data": data}); 
    }, 
    getImport: function (transportsId) { 
     var factory = this; 
     var deferred = $q.defer(); 
     var preFetchedTransport = this.findTransport(transportsId); 
     if (preFetchedTransport === null) { 
      console.log('fetching from backend'); 
      return $http.post("/import/create/" + transportsId).then(function (data) { 
       console.log('data fetched:'); 
       console.log(data); 
       factory.cacheTransport(transportsId, data); 
       deferred.resolve(data); 
      }); 
     } 
     preFetchedTransport = deferred.promise; 
     return preFetchedTransport; 
    }, 
    findTransport: function (transportsId) { 
     for (var i = 0; i < this.fetchedData.length; i++) { 
      var transportObj = this.fetchedData[i]; 
      if (transportObj.transportsId === transportsId) { 
       return transportObj.data; 
      } 
     } 
     return null; 
    } 
}; 

});

控制器

.controller('ImportController', function ($scope, $routeParams, importFactory){ 
    $scope.transportId = $routeParams.id; 
    importFactory.getImport($scope.transportId).then(function (successData) { 
     console.log('success'); 
     console.log(successData); 
    }, function (errorData) { 
     console.log('error'); 
     console.log(errorData); 
    }); 
+0

为什么不直接使用$ http的内置缓存,如$ http.post(url,{cache:true}) – 2015-03-19 12:25:48

+0

因为我需要更新缓存。 – 2015-03-19 12:27:46

回答

1

你基本上需要这样的:Demo here.

var cachedPromises = {}; 
return { 
    getStuff: function(id) { 
    if (!cachedPromises[id]) { 
     cachedPromises[id] = $http.post("/import/create/" + id).then(function(resp) { 
     return resp.data; 
     }); 
    } 
    return cachedPromises[id]; 
    } 
}; 

现在,当你获取这些数据,你可以操纵它会被改变,当你在未来的访问。

myService.getStuff(whatever).then(function(data) { 
    data.foo = 'abc'; 
}); 

//elsewhere 
myService.getStuff(whatever).then(function(data) { 
    console.log(data.foo); // 'abc' 
}); 

这里有一个演示,做这个,还有一个视图更新招(绑定的对象的视图中的数据进来之前),以及如何你可以分别从高速缓存更改数据的想法,以防你想拥有原始数据和不断变化的数据。 http://jsbin.com/notawo/2/edit

记得要避免那种令人讨厌的诺言反模式。如果您已经有承诺,请使用它,而不是用$q创建另一个。 $http已经返回承诺,并且如果您正确使用它,承诺就足以满足您的任何需求。

+1

再次非常感谢,向我展示了真正使用承诺的人:) – 2015-03-20 12:40:16

0

只是改变循环条件这个样子的,然后进行测试,我认为你的函数和推迟是做工精细,但循环不会发送正确的数据

for(var i = 0; i < this.fetchedData.length; i++) { 
     if (this.fetchedData[i].transportsId === transportsId) { 
      return this.fetchedData[i].data; 
     } 
    } 
    return null; 
} 
+0

它完全没有。另外谢谢。 – 2015-03-19 12:37:47

0

你没有定义的原因是你没有从$ http.post()。then()中返回任何东西!

同样在getImport()函数中,当传输已被缓存时,您将返回一个空承诺。您需要将其解析为已经缓存的传输对象。

getImport: function (transportsId) { 
    var factory = this; 
    var deferred = $q.defer(); 
    var preFetchedTransport = this.findTransport(transportsId); 
    if (preFetchedTransport === null) { 
     console.log('fetching from backend'); 
     return $http.post("/import/create/" + transportsId).then(function (data) { 
      console.log('data fetched:'); 
      console.log(data); 
      factory.cacheTransport(transportsId, data); 
      return data;    //this was missing 
     }); 
    } 

    // resolve it with transport object if cached 
    deferred.resolve(preFetchedTransport); 
    return deferred.promise; 
},