Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用angular2 http服务缓存结果_Angular_Typescript - Fatal编程技术网

使用angular2 http服务缓存结果

使用angular2 http服务缓存结果,angular,typescript,Angular,Typescript,我通过一个服务公开了一个HTTPGET请求,几个组件正在使用这个数据(关于用户的配置文件详细信息)。我希望第一个组件请求实际执行对服务器的HTTPGET请求并缓存结果,以便后续请求将使用缓存的数据,而不是再次调用服务器 下面是一个服务示例,您建议如何使用Angular2和typescript实现这个缓存层 import {Inject, Injectable} from 'angular2/core'; import {Http, Headers} from "angular2/http"; i

我通过一个服务公开了一个HTTPGET请求,几个组件正在使用这个数据(关于用户的配置文件详细信息)。我希望第一个组件请求实际执行对服务器的HTTPGET请求并缓存结果,以便后续请求将使用缓存的数据,而不是再次调用服务器

下面是一个服务示例,您建议如何使用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;
                }
            });
    }
}

关于您的最后一条评论,这是我能想到的最简单的方法:创建一个具有一个属性且该属性将保存请求的服务

类服务{
_数据;
获取数据(){
返回此。\u数据;
}
设置数据(值){
这个。_数据=值;
}
}
就这么简单。plnkr中的所有其他内容都将保持不变。我从服务中删除了请求,因为它将被自动实例化(我们不做
新服务…
,我不知道通过构造函数传递参数的简单方法)

现在,我们有了服务,我们现在要做的是在组件中发出请求,并将其分配给服务变量
data

class应用程序{
构造函数(http:http,svc:Service){
//一些动态id
设someDynamicId=2;
//在请求中使用动态id
svc.data=http.get('http://someUrl/someId/“+someDynamicId.share();
//订阅结果
svc.data.subscribe((结果)=>{
/*对结果做点什么*/
});
}
}
请记住,我们的服务实例对于每个组件都是相同的,因此当我们为
数据指定一个值时,它将反映在每个组件中

下面是一个示例

参考

运营商只在第一个请求上工作,当所有订阅都已提供且您创建了另一个订阅时,它将不工作,它将发出另一个请求。(这种情况非常常见,对于angular2 SPA,您总是创建/销毁组件)

我使用一个函数来存储http可观察的值。可观察对象可以为其订户提供以前的价值。

服务:

@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)
    );
}
    }
}
组件:

@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)
    );
}
    }
}
@组件({
选择器:“我的应用程序”,
模板:`getData from AppComponent`
})
导出类AppComponent{
构造函数(私有数据服务:数据服务){}
getData(){
这是.dataService.getData().subscribe(
请求数据=>{
log('ChildComponent',requestData);
},
//处理错误,否则将破坏可观察的
error=>console.log(错误)
);
}
}
}


(观察控制台和网络选项卡)

我省略了
用户ID处理。它需要管理一组
数据
和一组
可观察的
(每个请求的
用户ID一个)

从'@angular/core'导入{Injectable};
从'@angular/Http'导入{Http,Headers};
从“rxjs/Observable”导入{Observable};
导入“rxjs/observable/of”;
导入“rxjs/add/operator/share”;
导入'rxjs/add/operator/map';
从“./Data”导入{Data};
@可注射()
导出类数据服务{
私有url:string=https://cors-test.appspot.com/test';
私有数据:数据;
私人可观察的:可观察的


您可以在

上找到另一个有趣的解决方案,我想您正在寻找。我有一个解决方案,您可以看到它正在工作。请注意,这不是缓存,但它可能对您有效:)(运行一次并查看网络选项卡,然后从http.get
中删除
.share()
,然后查看差异)。我尝试了您的方法,但是当从两个不同的组件调用getUserProfile(with.share())时,GET请求仍然会在服务器上执行两次。这是因为使用@Inject(ProfileService)将ProfileService注入调用组件的两个构造函数中profileService。我在这里遗漏了什么?这取决于。如果在每个组件中注入服务,则会得到两个不同的实例(注入的意思是使用
提供程序/查看提供程序
)。如果是这种情况,则应只将其注入顶级组件(在这两个组件之间)。如果不是这样,您应该添加更多代码,如果可能的话,还应该添加一个repo。它们都使用ProfileService的同一个实例(我验证了这一点,放置了一些私有I整数,每次调用方法时递增一个,并将其打印到日志中,它打印0,1,2…因此这意味着每次都使用相同的实例)但是,由于某些原因,每次调用getUserProfile方法时,都会在服务器上再次执行GET请求。没错,我刚刚尝试过并遇到了相同的问题。我发现,使用该方法返回
共享()
,每次都会返回不同的共享太长了,读不下去了,但是如果你重构它,在构造函数中做出这个请求并把它赋值给变量,它就会起作用。TL;plnkr博士,例子是:嗨,很好的例子,但是它不起作用。例如,如果你有点击事件的请求,它会在每次EX:(点击蓝色方框并观察网络选项卡)。在我的应用程序中,我创建了一个新的ReplaySubject Observable来缓存HTTP,我想使用share()方法,但奇怪的是为什么在某些情况下它不起作用。啊,实际上我得到了它(经过一些测试和阅读rxjs文档),所以它将对所有现有订阅共享相同的可观察值,但一旦并没有订阅并且您创建了一个新的订阅,它将请求一个新的值,从而请求一个新的xhr请求。@Eric Martinez:plunker不再运行了…非常好的完整示例,即使使用了这个.observable check.the.share()是非常重要的,一开始不知道要找什么就不容易弄清楚