What is the best way to run multiple functions sequentially?

In my project, I am utilizing Angular 10. Within this project, I have implemented two functions named initData1 and initData2.

These are the two functions:

initData1(){
    // Perform HTTP client services

    this.dataService.getTitleImageUrl(this.data.titlId, this.data.id )
    .subscribe( resp => {  this.titleImageUrl = encodeURI(resp.results[0]) });

    this.storeService.getContactImageUrl(this.store.titlId, this.store.id)
    .subscribe( resp => {  this.contactImageUrl = encodeURI(resp.results[0]) });
}


initData2(){
   // Implement additional HTTP client services

    this.dataService.getTitleImageUrl(this.data.titlId, this.data.id )
    .subscribe( resp => {  this.titleImageUrl = encodeURI(resp.results[0]) });

    this.storeService.getContactImageUrl(this.store.titlId, this.store.id )
    .subscribe( resp => {  this.contactImageUrl = encodeURI(resp.results[0]) });
}

The execution of these functions in my component is as follows:

      ngOnInit(): void  {
        initData1();
        initData2();
      }
      

I am currently seeking a solution on how to ensure that the initData2 function is only executed after all HTTP client services are resolved in the initData1 function.

UPDATE: Included examples of HTTP client services for better understanding.

Answer №1

It's highly recommended to utilize the various functions and operators provided by RxJS when working with observables.

  1. Subscribe to observables only where their response is needed
  2. Avoid making unnecessary subscriptions

Based on these principles, here are some suggested modifications to your code:

initData1(): Observable<any> {  // <-- return observable here
  // Use `forkJoin` to trigger multiple observables in parallel
  return forkJoin({
    title: this.dataService.getTitleImageUrl(this.data.titlId, this.data.id),
    contact: this.dataService.getTitleImageUrl(this.data.titlId, this.data.id)
  }).pipe(
    // Utilize `tap` to apply side effects
    tap(imageUrls => {
      this.titleImageUrl = encodeURI(imageUrls.title.results[0]);
      this.contactImageUrl = encodeURI(imageUrls.contact.results[0]);
    })
  );
}

initData2(): Observable<any> {  // <-- return observable here
  // Use `forkJoin` to trigger multiple observables in parallel
  return forkJoin({
    title: this.dataService.getTitleImageUrl(this.data.titlId, this.data.id),
    contact: this.dataService.getTitleImageUrl(this.data.titlId, this.data.id)
  }).pipe(
    // Utilize `tap` to apply side effects
    tap(imageUrls => {
      this.titleImageUrl = encodeURI(imageUrls.title.results[0]);
      this.contactImageUrl = encodeURI(imageUrls.contact.results[0]);
    })
  );
}

You can also employ higher order mapping operators for co-dependent observables to map from one observable to another:

ngOnInit() {
  this.initData1().pipe(
    switchMap(imageUrls => this.initData2())
  ).subscribe(
    response => { 
      // Handle the response from `this.initData2()`
    },
    error => {
      // Manage errors appropriately
    }
  );
}

For more insights on managing nested subscriptions, refer to this link.

Answer №2

To seamlessly execute the second function, you can place a call to initData2(); within the response block of the first function.

initData1(){
    this.httpClient.get(yourURL).subscribe(response => {
        initData2();
    })
}

By structuring it in this manner, the functions will be invoked sequentially.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Application Initialization Error: appInits is not a valid function

When my Angular v17 application starts, I need to set some important values right away. This is how it's done in app.config.ts: export const appConfig: ApplicationConfig = { providers: [ ConfigService, ... { pr ...

I am interested in incorporating a delete button within my Angular application

I am working on an Angular App and I need to implement a remove button for a div element. Currently, I have an add button function in my ts file: uploads = []; addUp() { this.uploads.push(this.uploads.length); } I attempted to create the remove b ...

Input a new function

Trying to properly type this incoming function prop in a React Hook Component. Currently, I have just used any which is not ideal as I am still learning TypeScript: const FeaturedCompanies = (findFeaturedCompanies: any) => { ... } This is the plain fun ...

Exploring ng-bootstrap: A guide to accessing nested components

A scenario where a parent component contains a template with layers of nested components. In this structure, the tooltip is enclosed within the modal, which is further encapsulated within the tab. The challenge here is to access the innermost component ( ...

Guide on importing an external JavaScript library in Node.js utilizing a TypeScript declaration file

I am working on a Node.js project using Typescript and I am facing an issue with integrating mime.js (https://github.com/broofa/node-mime). Even though I have a declaration file available (https://github.com/borisyankov/DefinitelyTyped/blob/master/mime/mim ...

Enhancing Headers in Kendo UI Angular Grid

Within the footer of a grid, it is possible to include the following code in each column, with all values appearing in the same footer: <template kendoGridGroupFooterTemplate let-group="group" let-aggregates> <span class="pull-right"& ...

Disable router history tracking in Angular 2

One of our clients is iFraming our app into their website and they are concerned about how the router navigation within our app could affect the back button functionality on their site. We have attempted a few methods, such as utilizing post messages to e ...

No versions for "cra-template-typescript" that align with "latest" were located in our cache

Currently attempting to follow the steps outlined in this helpful guide: How to Develop a Basic React Application With an Express API. However, upon executing the command: npx create-react-app react-express-app --template typescript I encountered the foll ...

Guide to accessing contact list on Ionic framework

I'm new to using Ionic and I'm trying to access the contact list in my app to display contacts only. Can someone please guide me on how to achieve this? I watched a tutorial on YouTube but the code provided doesn't seem to work. I've ad ...

Avoiding duplicate subscriptions in Angular 4/5: a guide to streamlining

I'm looking for a streamlined way to capture a query parameter and subscribe to an API in order to retrieve results. Currently, I am using combineLatest but it seems a bit excessive. Is there a more efficient approach that focuses solely on the queryP ...

Error in Angular 8: The type of '[object Object]' is an object, whereas NgFor only supports binding to Iterables such as Arrays

I recently started using Angular 8 and I'm dealing with an issue while trying to fetch data from an http get request. I am attempting to iterate through the data using *ngFor but unfortunately encountering this error. Any suggestions on how to resolv ...

Identifying Gmail line breaks in the clipboard using Angular

I'm currently working on a feature that allows users to paste content from Gmail into a field and detect line breaks. The field doesn't have to be a text area, I just need to identify the line breaks. However, there seems to be an issue with det ...

Avoid using the Input formControlName in the Angular 6 form

Before submitting the form, I want to be able to retrieve the value of the input tag with formControlName. I have tried creating a method to accomplish this, but I am unable to access the current input value. When I removed the formControlName to exclude ...

Issues with calling Android Api (Okhttps) in Android versions 9 (Pie) and higher are being encountered

My Android API calls are functioning perfectly up to Oreo version (8), but I am facing issues with calling the API on Android 9 (Pie) and above. If there have been any changes in Pie, please advise. Thank you in advance. private void getLoginAPI(String ...

Using React and Typescript, implement an Ant Design Table that includes a Dropdown column. This column should pass

Next Row: { title: "Adventure", render: (item: ToDoItem) => { //<- this item return ( <Dropdown overlay={menu}> <Button> Explore <DownOutlined /> </Button> </Dropdown&g ...

No reply from Axios after using async await

Here's a simple method that utilizes Axios to make a call to an API. Interestingly, when the method is called, it doesn't display any output, no logs or error messages. async deActivate(product: Product): Promise<void> { try { ...

`Why am I unable to achieve the proper body shape with Angular?`

When using Angular to retrieve registration information from an HTML form and then posting it to an API path, everything seems to be working fine. However, the word "work" is being printed and I am unable to get the value in the body. I have tested the POS ...

When logging off from an Angular2 application, the OIDC-client does not properly clear the cookies for the MVC application

I currently have an authorization server that is being used by both my Angular2 app and MVC webapp. In my Angular2 app, I've implemented authorization using the oidc-client JavaScript package. Everything works well except for the logout functionality ...

Creating and utilizing multi-module NPM packages written in Typescript: A comprehensive guide

For a while now, I've been quite at ease creating and utilizing NPM packages with Typescript. However, these packages have typically been provided and consumed as a single module. Now, I'm interested in publishing packages that contain more than ...

The error message "Unable to instantiate Jest, Enzyme, React, Next.js, Typescript .default" indicates that the default

I am trying to create a basic test to ensure that my next.js page loads correctly. I followed an informative tutorial, but I encountered an error related to the use of simple-react-validator when running tests using Jest: TypeError: simple_react_validat ...