Angularjs 出厂延迟数据消失

Angularjs Factory deferred's data disapearing

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

以下的控制台输出:

获取的数据:
对象{状态:"OK",数据:对象,errorMessage:null,异常:null}
成功
未定义

导入工厂:

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

只需像这样更改循环条件然后测试我认为您的函数和延迟工作正常但循环未发送正确的数据

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

你未定义的原因是你没有从 $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;
},

你基本上需要这个: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 已经 returns 一个承诺,如果你正确使用它,这个承诺足以满足你的任何需要。