从rxjs订阅返回一个函数

时间:2018-03-08 15:38:42

标签: javascript angular typescript rxjs

这是一个关于使用angular-l10n翻译模块的问题,但由于它是一个更具打字稿的特定问题,我在这里发布。

要动态配置模块(例如设置默认语言),我必须使用以下方法:

load(): Function {
  this.localeConfig.language = 'en';
  return () => this.l10nLoader.load();
}

localeConfigl10nLoader都被注入。

必须在最后执行

return () => this.l10nLoader.load();才能在配置后实际显示页面。

  

我想要做的是从api加载语言然后设置配置。

我在一个返回Observable的服务中执行此操作,然后在load()函数内订阅它。

load(): Function {
  this.languageService.getDefaultLanguage().subscribe(
    lang => {
      this.localeConfig.language = lang;
      return ???
    }
  );
}
  

问题是:我不知道如何在订阅结束时返回this.l10nLoader.load();。如果我在函数结束时返回它,则在订阅结束之前完成。

如何在订阅完成后返回Function类型的东西?

3 个答案:

答案 0 :(得分:1)

您无法使用return执行此操作,因为load()函数是异步的。我建议您做的是将load()返回值更改为Observable<Function>并在其中创建new Observable

以下是代码段:

load(): Observable<Function> {
   return new Observable(observer => {
       this.languageService.getDefaultLanguage().subscribe(
          lang => {
             this.localeConfig.language = lang;
             observer.next(this.l10nLoader.load);
             observer.complete();
          }
       );
   });
}

之后,您可以通过以下方式调用此功能:

load().subscribe(fn => fn());

答案 1 :(得分:0)

在Vanilla JS中,你使用回调。

例如,你可以这样做:

load(cb: Function): Function {
  this.languageService.getDefaultLanguage().subscribe(lang => {
    this.localeConfig.language = lang;
    cb(lang);
  });
}

现在,您可以像这样调用您的函数:

this.myL10nService.load(lang => {
  console.log('selected language is ' + lang);
});

答案 2 :(得分:0)

我找到了一个有效的解决方案 使用.toPromise()代替.subscribe()然后返回l10nLoader.load();作为Promise的结果解决了我的问题。

语言configuration.service:

@Injectable()
export class LocalizationConfig {
  constructor(
      public l10nLoader: L10nLoader,
      @Inject(TRANSLATION_CONFIG) private translationConfig: TranslationConfig,
      @Inject(LOCALE_CONFIG) private localeConfig: LocaleConfig,
      private language: LanguageService
  ) { }

  load(): Promise<void> {
    return this.language.getUserLanguages().toPromise()
    .then(
      res => {
        this.localeConfig.language = res.language;
        return this.l10nLoader.load(); // this is important!!
      })
    .catch(  
      err => {
        // set default language or desired strategy
        return this.l10nLoader.load();   
      }
    );
  }
}

export function initLocalization(localizationConfig: LocalizationConfig): Function {
  return () => localizationConfig.load();
}

app.module:

providers: [
  ...
  {
    provide: APP_INITIALIZER,
    useFactory: initLocalization,
    deps: [LocalizationConfig],
    multi: true,
  },
  ...