角度:防止使用同一服务的管道发出多个请求

时间:2019-09-23 17:27:28

标签: angular rxjs

我正在尝试构建一个模块,以允许Angular使用Fluent进行翻译。我创建了一个服务和一个管道,允许在任何Angular项目中使用Fluent。一旦第一个管道执行完毕,服务就会检查转译文件是否已经缓存,否则将其下载。

https://gitlab.com/tobias47n9e/angular-fluent/blob/master/angular-fluent/src/lib/angular-fluent.service.ts#L66

private fetchTranslationsAndResolveKey(
    key: string,
    options: any,
    locale: string,
): Observable<string> {
    return this.http
        .get(`assets/i18n/${locale}.ftl`, { responseType: 'text' })
        .pipe(
            map((content: string) => {
                this.translationsMap[locale] = content;
                this.fetchingFile = false;
                return this.resolveKey(key, options, locale);
            }),
            concatAll(),
        );
}

但是,似乎每个管道都在获取它自己的该可观察链的副本,或者某些东西无法等待第一个请求。有什么好的模式可以避免多次下载翻译文件?

管道:

@Pipe({
name: 'fluent',
pure: false,
})
export class FluentPipe implements PipeTransform {
locale: BehaviorSubject<string>;

constructor(private fluentService: AngularFluentService) {}

transform(key: string, args?: any): Observable<string> {
    if (!this.locale) {
        this.locale = this.fluentService.locale;
        this.locale.subscribe(locale => {
            if (locale) {
                return this.fluentService.translate(
                    key,
                    args,
                    getLocale(args),
                );
            }
        });
    }

    return this.fluentService.translate(key, args, getLocale(args));
}
}

将状态保留在服务中的当前解决方案:

2 个答案:

答案 0 :(得分:0)

我不太确定这个插件如何工作,但是我认为您需要的是as转换运算符

您可以让模板中的根节点使用异步管道,该管道可以将结果分配给变量,一旦准备好就可以在模板中使用

<ng-container *ngIf="data | custPipeReturningObservable$ | async as num">
    {{num}}
</ng-container>

stackblitz https://stackblitz.com/edit/angular-async-with-custom-pipe中的模式详细信息,在该示例中,我尝试将自定义管道链接到返回带有异步管道的可观察项

答案 1 :(得分:0)

AngularFluentService为您传递给translationsMap:12的给定语言环境维护翻译的地图(AngularFluentService::translate)。如果地图不包含语言环境,它将发出一个http请求,但随后使用相同语言环境对translate进行的所有调用都会从地图中检索翻译,而不发出请求。因此,您需要在管道中执行的所有操作如下:

@Pipe({
  name: 'fluent'
})
export class FluentPipe implements PipeTransform {

  constructor(private fluentService: AngularFluentService) {
  }

  transform(key: string, args?: any): Observable<string> {
    return this.fluentService.translate(key, args, getLocale(args));
  }
}