Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/33.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
Angular 5-持久化数据并避免后续API调用_Angular_Rxjs_Angular5 - Fatal编程技术网

Angular 5-持久化数据并避免后续API调用

Angular 5-持久化数据并避免后续API调用,angular,rxjs,angular5,Angular,Rxjs,Angular5,“@angular/core”:“^5.2.0” “rxjs”:“^5.5.6” 我是angular框架的新手,目前正在利用它创建一个可注入的服务类,它将调用WebAPI从后端数据库中提取数据 我希望保留或避免使用此服务类的组件的后续调用。因为它是一个被反复调用的数据 我觉得我犯了一个很小的错误,没能抓住它。我想避免第二个电话的往返在第一次调用期间,我希望将数据保存在_dynda对象中。但不知何故,每次服务调用都会打印console.log(“Fresh call”)语句 请说明我在哪里犯了错误

“@angular/core”:“^5.2.0”

“rxjs”:“^5.5.6”

我是angular框架的新手,目前正在利用它创建一个可注入的服务类,它将调用WebAPI从后端数据库中提取数据

我希望保留或避免使用此服务类的组件的后续调用。因为它是一个被反复调用的数据

我觉得我犯了一个很小的错误,没能抓住它。我想避免第二个电话的往返在第一次调用期间,我希望将数据保存在_dynda对象中。但不知何故,每次服务调用都会打印console.log(“Fresh call”)语句

请说明我在哪里犯了错误。我想使用内置的角度变化检测功能

我的服务级别如下:-

@Injectable()

export class DynamicDataService {

    private _dyndata: DynamicContent[];

    constructor(private _httpObj: HttpClient, private http: Http) {
    }

    headers = new HttpHeaders({
        'Content-Type': 'application/json'
    });

    getdynamiccontent(): Observable<DynamicContent[]> {

        if (this._dyndata) {
            console.log('data exists!')
            return of(this._dyndata);
        }

        console.log('Fresh call');

        return this._httpObj.get<DynamicContent[]>(environment.apiHost + 'DynamiContentforPage')
            .pipe(tap(data => this._dyndata = data)
            ); 
    }
@Injectable()
导出类服务{
私人:动态内容[];
构造函数(私有的_httpObj:HttpClient,私有的http:http){
}
headers=新的HttpHeaders({
“内容类型”:“应用程序/json”
});
getdynamiccontent():可观察{
如果(这个){
console.log('数据存在!')
归还(本文件);
}
console.log('Fresh call');
返回此。\u httpObj.get(environment.apiHost+'dynamiccontentforpage')
.pipe(水龙头(数据=>this.\u dynda=数据)
); 
}
使用此服务类的组件如下所示:-

  import { Component, ElementRef, Input, Renderer, OnInit, Inject, DoCheck } from '@angular/core';
    import { DynamicDataService } from './dynamicdata.service';
    import 'rxjs/add/operator/filter';
    import { DynamicContent } from '../interfaces/IDynamicContent';

@Component({
    selector: 'CMSBlock',
    template: `<div [innerHTML]="_dynmarkup | keepHtml"></div>`,
    providers: [DynamicDataService]
})

export class DynamicDataComponent {
    public markupcollection: DynamicContent[];
    public savedmarkup: DynamicContent[];
    @Input('key') key: string;
    public _dynmarkup: any = '';

    constructor(private dynamicdataService: DynamicDataService) {
        console.log('cstor :: dynamicdata comp');
        this.getCMSData();
    }

    public getCMSData() {
        this.dynamicdataService.getdynamiccontent()
            .subscribe(px => {
                this.setUsersArray(px);
                console.log(this.markupcollection);
            });

    }

    setUsersArray(data) {
        this.savedmarkup = data;
        if (this.savedmarkup != undefined) {
            var item = this.savedmarkup.find(fx => fx.Key == this.key);
            this._dynmarkup = item.Text

        }
    }

}
从'@angular/core'导入{Component,ElementRef,Input,Renderer,OnInit,Inject,DoCheck};
从“./dynamicata.service”导入{DynamicDataService};
导入'rxjs/add/operator/filter';
从“../interfaces/IDynamicContent”导入{DynamicContent};
@组成部分({
选择器:“CMSBlock”,
模板:``,
提供者:[动态CDATA服务]
})
导出类组件{
公开集市:动态内容[];
公共存储标记:DynamicContent[];
@输入('key')键:字符串;
public _dynmarkup:any='';
构造函数(专用dynamicdataService:dynamicdataService){
log('cstor::dynamicatacomp');
这个.getCMSData();
}
公共getCMSData(){
this.dynamicdataService.getdynamiccontent()
.订阅(px=>{
这个.setUsersArray(px);
console.log(this.markupcollection);
});
}
setUsersArray(数据){
this.savedmarkup=数据;
if(this.savedmarkup!=未定义){
var item=this.savedmarkup.find(fx=>fx.Key==this.Key);
此.\u dynmarkup=item.Text
}
}
}

您遇到了一个非常有趣的案例

您的问题解决方案的简短答案是从组件提供商中删除
dynamicataservice
,并将其包含在更合适的位置,如

现在让我们深入研究这个问题,在angular中使用服务时,我们将它们包括在我们想要使用它们的模块/组件的提供者中(在您的例子中是
CMSBlock
),这样您就可以访问该服务,并且可以调用您的
API
并加载所需的数据。但正如我们所知,这些服务是这样的,即一旦提供就可以访问hall应用程序,因此人们可以问自己,当我们使用相同的令牌(名称),或多次使用同一服务
(其效果与使用相同名称提供不同服务相似)答案是,最后一个赢了,或者换句话说,最后一个提供的服务将覆盖为服务
令牌提供的功能

在您的情况下,当您多次使用
CMSBlock
组件时,您将提供/初始化两次
DynamicDataService
,这意味着每次调用该服务时,
\u dyndata
都处于初始状态,在您的情况下,它是空的,t汉克斯说,有人打了一个“新电话”

解决此问题的最佳方法是在关闭父模块中提供服务(如果您在延迟加载模块中使用此服务),或者在
根模块中提供服务(如果您在快速加载模块中使用此服务)

编辑:

第二个调用也可能发生在第一个调用完成之前,这将导致对Available
\u dynda
的检查失败


这是一个现场演示,演示了我所讨论的内容:

从对问题的评论来看,您似乎正在实例化组件的两个实例,它们都是在完成请求之前启动请求的

因此,要解决这个问题,您需要重新构造服务处理请求的方式。我建议使用服务上的BehaviorSubject提供详细信息,如下所示:

@Injectable()
export class DynamicDataService {

    private _dyndata: BehaviorSubject<DynamicContent[]> = new BehaviourSubject<DynamicContent[]>(null);
    private _requested: boolean = false;

    constructor(private _httpObj: HttpClient, private http: Http) {
    }

    headers = new HttpHeaders({
        'Content-Type': 'application/json'
    });

    getdynamiccontent(): Observable<DynamicContent[]> {
        if (!this._requested) {
            this._requested = true;
            console.log('Fresh call');
            this._httpObj.get<DynamicContent[]>(environment.apiHost + 'DynamiContentforPage')
            .subscribe(data => this._dyndata.next(data));
        } else {
            console.log('Request already made');
        }
        return this._dyndata.asObservable().pipe(filter((e) => e != null), take(1));
    }
}
@Injectable()
导出类服务{
private _dynda:BehaviorSubject=新行为主体(null);
private\u requested:boolean=false;
构造函数(私有的_httpObj:HttpClient,私有的http:http){
}
headers=新的HttpHeaders({
“内容类型”:“应用程序/json”
});
getdynamiccontent():可观察{
如果(!此._请求){
这是._request=true;
console.log('Fresh call');
这是.\u httpObj.get(environment.apiHost+'dynamiccontentforpage')
.subscribe(数据=>this._dynda.next(数据));
}否则{
log('已发出请求');
}
把这个还给我
private cachedRequest = this._httpObj.get(...).pipe(
  shareReplay(1),
  take(1),
)

getdynamiccontent() {
  return this.cachedRequest;
}