Angular 17中TranslocoLoader的Observable仅触发一次问题
问题:TranslocoLoader的Observable写法多次调用仅首次执行map逻辑
我实现了如下TranslocoLoader服务:
// transloco-loader.ts import { inject, Injectable } from '@angular/core'; import {TranslocoLoader } from '@ngneat/transloco'; import { map, take} from 'rxjs'; import { CFV2 } from '@go/shared-data-access-angular-config'; @Injectable({ providedIn: 'root' }) export class TranslocoHttpLoader implements TranslocoLoader { private _configFacade = inject(CFV2.ConfigFacade); getTranslation(lang: string) { // 每次都会执行到这里 console.log('function gets called each time'); return this._configFacade.configState$.pipe( take(1), map((state) => { // 但这里仅执行一次!即使configState$没有变化! console.log('But we get here ONLY ONCE!'); return { t: 'something' }; }), ); } }
当我调用getTranslation方法两次(针对同一语言)时,仅第一次会进入pipe中的map操作。我使用的是Angular 17,请问忽略了什么?
我通过async语法解决了该问题:
async getTranslation(lang: string): Promise<{ t: string }> { console.log('function gets called each time'); const state = await firstValueFrom( this._configFacade.configState$.pipe(take(1)), ); console.log('And we get here each time too!'); return { t: 'something' }; }
但我仍想了解为何Observable写法无法正常工作!
原因分析
核心问题出在Transloco的内置缓存机制:
- 当
getTranslation返回Observable类型结果时,Transloco会对相同语言的翻译请求做缓存:第一次调用时,它会订阅你返回的Observable,拿到结果后直接缓存;第二次调用同一语言的getTranslation时,Transloco会直接返回缓存的结果,不会再去订阅你新生成的Observable,因此map里的逻辑不会执行。 - 而改用
async/await返回Promise时,每次调用getTranslation都会生成一个全新的Promise实例。Transloco对Promise的处理逻辑是,即使是同一语言,也会等待这个新Promise完成(其缓存机制未对Promise做复用),因此每次都会执行到await后的代码。
另外补充:你的configState$如果是BehaviorSubject这类热Observable,本身会保留最新值,但问题的核心不在Observable的冷热属性,而是Transloco的缓存逻辑导致第二次没有订阅新的Observable。
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

