我通过一个服务公开了一个HTTP GET请求,几个组件正在使用这个数据(一个用户的配置文件细节)。我希望第一个组件请求实际执行对服务器的HTTP GET请求并缓存结果,这样后续的请求将使用缓存的数据,而不是再次调用服务器。
这里有一个服务的例子,你会建议如何用Angular2和typescript实现这个缓存层。
import {Inject, Injectable} from 'angular2/core';
import {Http, Headers} from "angular2/http";
import {JsonHeaders} from "./BaseHeaders";
import {ProfileDetails} from "../models/profileDetails";
@Injectable()
export class ProfileService{
myProfileDetails: ProfileDetails = null;
constructor(private http:Http) {
}
getUserProfile(userId:number) {
return this.http.get('/users/' + userId + '/profile/', {
headers: headers
})
.map(response => {
if(response.status==400) {
return "FAILURE";
} else if(response.status == 200) {
this.myProfileDetails = new ProfileDetails(response.json());
return this.myProfileDetails;
}
});
}
}
关于您的最后一条评论,这是我能想到的最简单的方法:创建一个将具有一个属性的服务,该属性将保存请求。
class Service {
_data;
get data() {
return this._data;
}
set data(value) {
this._data = value;
}
}
就这么简单。plnkr中的其他所有东西都不会受到影响。我从服务中删除了请求,因为它将被自动实例化(我们不做< code >新服务...,并且我不知道通过构造函数传递参数的简单方法)。
现在,我们有了服务,我们现在要做的是在组件中发出请求,并将其分配给服务变量data
class App {
constructor(http: Http, svc: Service) {
// Some dynamic id
let someDynamicId = 2;
// Use the dynamic id in the request
svc.data = http.get('http://someUrl/someId/'+someDynamicId).share();
// Subscribe to the result
svc.data.subscribe((result) => {
/* Do something with the result */
});
}
}
请记住,我们的服务实例对于每个组件都是相同的,因此当我们将值分配给data
时,它将反映在每个组件中。
这是plnkr的一个工作示例。
参考
我省略了userId
处理。相反,它需要管理data
数组和可观察
数组(每个请求的userId
一个)。
import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/observable/of';
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/map';
import {Data} from './data';
@Injectable()
export class DataService {
private url:string = 'https://cors-test.appspot.com/test';
private data: Data;
private observable: Observable<any>;
constructor(private http:Http) {}
getData() {
if(this.data) {
// if `data` is available just return it as `Observable`
return Observable.of(this.data);
} else if(this.observable) {
// if `this.observable` is set then the request is in progress
// return the `Observable` for the ongoing request
return this.observable;
} else {
// example header (not necessary)
let headers = new Headers();
headers.append('Content-Type', 'application/json');
// create the request, store the `Observable` for subsequent subscribers
this.observable = this.http.get(this.url, {
headers: headers
})
.map(response => {
// when the cached data is available we don't need the `Observable` reference anymore
this.observable = null;
if(response.status == 400) {
return "FAILURE";
} else if(response.status == 200) {
this.data = new Data(response.json());
return this.data;
}
// make it shared so more than one subscriber can get the result
})
.share();
return this.observable;
}
}
}
Plunker示例
你可以在https://stackoverflow.com/a/36296015/217408找到另一个有趣的解决方案
共享()运算符只在第一个请求时工作,当所有订阅都已服务并创建另一个订阅时,它将不工作,它将发出另一个请求。(这种情况很常见,对于angular2 SPA,您总是创建/销毁组件)
我使用ReplaySubject来存储http observable中的值。可观察的ReplaySubject可以为其订户提供以前的值服务:
@Injectable()
export class DataService {
private dataObs$ = new ReplaySubject(1);
constructor(private http: HttpClient) { }
getData(forceRefresh?: boolean) {
// If the Subject was NOT subscribed before OR if forceRefresh is requested
if (!this.dataObs$.observers.length || forceRefresh) {
this.http.get('http://jsonplaceholder.typicode.com/posts/2').subscribe(
data => this.dataObs$.next(data),
error => {
this.dataObs$.error(error);
// Recreate the Observable as after Error we cannot emit data anymore
this.dataObs$ = new ReplaySubject(1);
}
);
}
return this.dataObs$;
}
}
组件:
@Component({
selector: 'my-app',
template: `<div (click)="getData()">getData from AppComponent</div>`
})
export class AppComponent {
constructor(private dataService: DataService) {}
getData() {
this.dataService.getData().subscribe(
requestData => {
console.log('ChildComponent', requestData);
},
// handle the error, otherwise will break the Observable
error => console.log(error)
);
}
}
}
完全工作的PLUNKER
(观察控制台和网络选项卡)
结果缓存 1,用于加速热门数据的访问速度,Dubbo 提供声明式缓存,以减少用户加缓存的工作量 2。 缓存类型 lru 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。 threadlocal 当前线程缓存,比如一个页面渲染,用到很多 portal,每个 portal 都要去查用户信息,通过线程缓存,可以减少这种多余访问。 jcache 与 JSR107 集成,可以桥接各种缓存实现。 缓存
我正在使用Jmeter对我的ASP.NET应用程序进行负载测试。 我正在测试搜索功能,什么是在获得结果的响应时间。 我面临的问题是,当我第一次搜索时,说我搜索了“我很好”,并说它花了9876毫秒,下次我搜索同样的东西只需要4567毫秒,第三次只需要4234毫秒。 我正在使用HTTP缓存管理器,我已经检查了“每次迭代都清除缓存”。我还使用了Http Cookie管理器,并检查了“每次迭代清除Cook
Quarkus有类似于开箱即用?(在文件中找不到任何提及) 要穿上某种服务方式, 这将在一段时间内保留/缓存prev响应,并保留调用堆栈/日志。 类似于那个Spring注释?
问题内容: 我对来自JQuery Ajax请求的Internet Explorer缓存结果存在严重问题。 我的网页上有标题,每次用户导航到新页面时标题都会更新。页面加载后,我就执行此操作 它只是将标头信息注入页面。您可以通过访问www.wikipediamaze.com进行检查,然后登录并开始创建新拼图。 在我测试过的每种浏览器(谷歌浏览器,Firefox,Safari,Internet Expl
问题内容: 我在Internet Explorer中的页面出现问题。我有一个Ajax调用,在其他浏览器中,当我单击该链接时,该调用会传递到控制器中并正确加载数据。但是在IE中,一次加载后,它消失了,而我却没有通过控制器就获得了相同的旧结果。 问题答案: 尝试: 放置在控制器类中的此属性禁用缓存。由于不需要在应用程序中缓存,因此将其放置在BaseController类中: 这是有关OutputCac
我正在实现一个使用Swift Stack的Joss客户机调用外部服务的Lagom服务。如何缓存此信息以避免每次调用服务时都调用外部服务?