简体   繁体   中英

Return a function from a rxjs subscription

This is a question about using the angular-l10n translation module, but since it's a more typescript specific question i post it here.

To dynamically configure the module (and for example set the default language), i have to use the following method:

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

localeConfig and l10nLoader are both injected.

return () => this.l10nLoader.load(); has to be executed at the end to actually show the page after configuration.

What i would like to do is to load the language from an api and then set the configuration.

I do this in a service which returns an Observable and then subscribe to it inside of the load() function.

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

The problem is: I don't know how to return this.l10nLoader.load(); at the end of the subscription. If i return it at the end of the function it is done before the subscription ends.

How do i return something of type Function after the subscription is finished?

You cannot do this with return , because the load() function is asynchronous. What I suggest to do, is change load() return value to Observable<Function> and create new Observable inside it.

Here is the code snippet:

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

After that you can call this function in the following way:

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

In Vanilla JS, you use callbacks for that.

For instance, you could do this :

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

Now, you can call your function like this :

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

I found a working Solution.
Using .toPromise() instead of .subscribe() and then returning l10nLoader.load(); as the result of the Promise solved my problem.

language-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,
  },
  ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM