Synchronous initalisation of multiple Observables/Promises in ngOnInit()?

Viewed 34

Im relative new to Angular/typescript and have following problem. Probably very trivial for most of you. In my ngOnInit() im trying to retrieve settings stored in my backend via a GET request. Afterwards i need to start to subscribe to an observable. The observable is starting to fill the widgets (content wise/they change over time) while the settings give me the number/type of widgets that will be shown.

Basically, to have the ngOnInit() wait for the getGeneralSettingsOnce response and afterwards to start some other subscriptions.

My request function:

getGeneralSettingsOnce(): Promise<any> {
    return this.http.get(`${environment.API_URL}/get_general_settings`).toPromise()
    .then(response => {
      return response
    })
  }

My first attempt was to just make the ngOnInit of my main page an async function and await the promise. -> This leads to the Cannot read properties of undefined (reading '-1') for some static widgets within my main page. According to an article i read this might be caused because my main page is not completly loaded while the browser is already tyring to render the page?(Not quiet sure) Source: article

Parts of my ngOnInit of my main page

async ngOnInit() {  
    let generalSettings = await this.localService.getGeneralSettingsOnce(); //calling the promise
    this.widgetCount = generalSettings.widget_count

    // other subsrciptions
    this.localService.getWidgetContent().subscribe(
      data => { this.loadWidgetContent(data)
      } 
    }
}

So my question is how can i archive my goal to init the settings first and subsribe to other request functions afterwards like it would be synchronous. Preferable without getting errors.

1 Answers

You can go for a subscribe (common way to get data from observables) combined with switchMap , which can execute one observable after another!

    subscription: Subscription = new Subscription(); // <- stores observables to unsubscribe

    ngOnInit() {
        this.subscription.add( // <- add the subscription to a single place
            this.localService
                .getGeneralSettingsOnce()
                .pipe(
                    switchMap(generalSettings => {
                        this.widgetCount = generalSettings.widget_count;
                        // other subsrciptions
                        return this.localService.getWidgetContent();
                    })
                )
                .subscribe(data => {
                    this.loadWidgetContent(data);
                })
        );
    }

    ngOnDestroy() {
        this.subscription.unsubscribe(); // <- subscribers must be unsubscribed to prevent memory leaks
    }
Related