211

我希望能够创建一个自定义 AngularJS 服务,该服务在其数据对象为空时发出 HTTP 'Get' 请求,并在成功时填充数据对象。

下次调用此服务时,我想绕过再次发出 HTTP 请求的开销,而是返回缓存的数据对象。

这可能吗?

4

7 回答 7

317

Angular 的$http有一个内置的缓存。根据文档:

cache – {boolean|Object} – 使用 $cacheFactory 创建的布尔值或对象,用于启用或禁用 HTTP 响应的缓存。有关详细信息,请参阅 $http 缓存

布尔值

因此,您可以在其选项中设置cachetrue :

$http.get(url, { cache: true}).success(...);

或者,如果您更喜欢配置类型的调用:

$http({ cache: true, url: url, method: 'GET'}).success(...);

缓存对象

您还可以使用缓存工厂:

var cache = $cacheFactory('myCache');

$http.get(url, { cache: cache })

您可以使用$cacheFactory自己实现它(特别是在使用 $resource 时):

var cache = $cacheFactory('myCache');

var data = cache.get(someKey);

if (!data) {
   $http.get(url).success(function(result) {
      data = result;
      cache.put(someKey, data);
   });
}
于 2013-01-02T06:25:38.020 回答
48

我认为现在有一个更简单的方法。这为所有 $http 请求($resource 继承)启用了基本缓存:

 var app = angular.module('myApp',[])
      .config(['$httpProvider', function ($httpProvider) {
            // enable http caching
           $httpProvider.defaults.cache = true;
      }])
于 2013-08-06T00:35:32.150 回答
12

在当前稳定版本 (1.0.6) 中执行此操作的更简单方法需要更少的代码。

设置模块后添加工厂:

var app = angular.module('myApp', []);
// Configure routes and controllers and views associated with them.
app.config(function ($routeProvider) {
    // route setups
});
app.factory('MyCache', function ($cacheFactory) {
    return $cacheFactory('myCache');
});

现在您可以将其传递给您的控制器:

app.controller('MyController', function ($scope, $http, MyCache) {
    $http.get('fileInThisCase.json', { cache: MyCache }).success(function (data) {
        // stuff with results
    });
});

一个缺点是键名也是自动设置的,这可能会使清除它们变得很棘手。希望他们会以某种方式添加以获得关键名称。

于 2013-05-04T19:21:58.363 回答
7

如果您喜欢 $http 的内置缓存但想要更多控制权,请查看angular-cache库。您可以使用它通过生存时间、定期清除以及将缓存持久化到 localStorage 的选项来无缝地增加 $http 缓存,以便跨会话使用它。

FWIW,它还提供了工具和模式,使您的缓存成为一种更动态的数据存储,您可以作为 POJO 与之交互,而不仅仅是默认的 JSON 字符串。目前无法评论该选项的实用性。

(然后,最重要的是,相关库angular-data是 $resource 和/或 Restangular 的替代品,并且依赖于 angular-cache。)

于 2014-08-27T06:57:38.373 回答
5

由于 AngularJS 工厂是单例的,您可以简单地存储 http 请求的结果,并在下次将服务注入某些东西时检索它。

angular.module('myApp', ['ngResource']).factory('myService',
  function($resource) {
    var cache = false;
    return {
      query: function() {
        if(!cache) {
          cache = $resource('http://example.com/api').query();
        }
        return cache;
      }
    };
  }
);
于 2016-01-12T04:21:04.943 回答
2
angularBlogServices.factory('BlogPost', ['$resource',
    function($resource) {
        return $resource("./Post/:id", {}, {
            get:    {method: 'GET',    cache: true,  isArray: false},
            save:   {method: 'POST',   cache: false, isArray: false},
            update: {method: 'PUT',    cache: false, isArray: false},
            delete: {method: 'DELETE', cache: false, isArray: false}
        });
    }]);

设置缓存为真。

于 2016-04-07T11:28:32.823 回答
-2

在 Angular 8 中,我们可以这样做:

import { Injectable } from '@angular/core';
import { YourModel} from '../models/<yourModel>.model';
import { UserService } from './user.service';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})

export class GlobalDataService {

  private me: <YourModel>;

  private meObservable: Observable<User>;

  constructor(private yourModalService: <yourModalService>, private http: HttpClient) {

  }

  ngOnInit() {

  }


  getYourModel(): Observable<YourModel> {

    if (this.me) {
      return of(this.me);
    } else if (this.meObservable) {
      return this.meObservable;
    }
    else {
      this.meObservable = this.yourModalService.getCall<yourModel>() // Your http call
      .pipe(
        map(data => {
          this.me = data;
          return data;
        })
      );
      return this.meObservable;
    }
  }
}

你可以这样称呼它:

this.globalDataService.getYourModel().subscribe(yourModel => {


});

上面的代码将在第一次调用时缓存远程 API 的结果,以便可以在对该方法的进一步请求中使用它。

于 2019-10-17T12:31:44.267 回答