Angularjs Factory延期数据消失

时间:2015-03-19 12:13:41

标签: javascript angularjs factory deferred

我试图为http请求做一个缓存工厂,因此它不会让服务器为同一个请求做很多工作。但似乎我的方式是使用deferred" swallows"数据,我不知道为什么。

下面的控制台输出:

提取

数据:
对象{state:" OK",data:Object,errorMessage:null,exception:null}
成功
未定义

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

3 个答案:

答案 0 :(得分: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 :(得分:0)

只是改变循环条件看起来像这样然后测试我认为你的函数和延迟工作正常但循环没有发送正确的数据

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

答案 2 :(得分:0)

您未定义的原因是您没有从$ http.post()返回任何内容。然后()!

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

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