0

There is a a newData array and rxjs forkJoin operator with two methods. I'm trying to populate the array within getNewData() in order to use it in forkJoin subscription, but it's still undefined. Which would be the appropriate way to wait for newData array to be populated in getNewData() in order to use it in forkJoin subscription?

    newData = [];
    
    forkJoin(
      this.method1();
      this.method2()
    ).subscribe({ data1, data2 }) => {
       const filteredData = data1.filter(item => item.id === model.id);
       this.getNewData(filteredData);

       console.log(this.newData) => undefined

       // wait for this.newData?
    }

    // Observable
    getNewData(filteredData) {
      return this.API('GET', `data/${filteredData.id}`).pipe(map((resp: any) => {
          this.newData = resp;
        }));
    }

3 Answers 3

1

You're attempting nested subscription which is discouraged.

If the calls are entirely independent of each other, you could append this.API('GET', 'data') call as third argument to the forkJoin function.

import { forkJoin } from 'rxjs';

newData = [];

forkJoin(
  this.method1(),
  this.method2(),
  this.API('GET', `data`)
).subscribe([ data1, data2, newData ]) => {
  const filteredData = data1.filter(item => item.id === model.id);
  this.newData = newData;
  console.log(this.newData);
}

Or if the API call somehow depends on the data from the first two methods, then you could use one of the RxJS higher order mapping operators like switchMap.

import { forkJoin } from 'rxjs';
import { swithcMap } from 'rxjs/operators';

newData = [];

forkJoin(
  this.method1(),
  this.method2()
).pipe(
  switchMap(([data1, data2]) => {
    const filteredData = data1.filter(item => item.id === model.id);
    return this.getNewData(filteredData);
  })
).subscribe(newData => {
  this.newData = newData;
  console.log(this.newData);
}

getNewData (filteredData): Observable<any> {
  return this.API('GET', `data/${filteredData.id}`).pipe(
    map((resp: any) => {
      this.newData = resp;
    })
  );
}

Update (accd. to OP's update):

  1. You wish to use the output from forkJoin inside another HTTP call. Then you'd need to switchMap operator as shown.

  2. (Unrelated to the issue) Please try to provide notes like this when you update something in the original post. It makes it easier to understand your intent.

Sign up to request clarification or add additional context in comments.

Comments

1

Use combineLatest from RxJS and use filter(), tap() to check for the data

combineLatest(
    this.method1(),
    this.method2(),
    this.getNewData()
).pipe(
    filter(data => !!data), 
    tap(data => console.log(data)) 
    catchError(error => console.log(error))
).subscribe(
  [dataFromMethod1, dataFromMethod2, dataFromMethod3] => {
   // This will subscribe only if all the observables return data
   // Otherwise it will go to catchError
})


// Filter will check if the data is present or not.
// Tap will return the data before subscribing
// catchError ==> Subscription errors are caught in this catchError

2 Comments

I've updated to the question; there is a filteredData which need to be passed to getNewData method so in that case I think it would be appropriate to use switchMap as @Michael D suggested
That makes sense!
1

Simply add method getNewData to forkjoin as third argument, and you will have newData inside your sub

    forkJoin(
      this.method1();
      this.method2(), 
      this.getNewData() 
    ).subscribe([ data1, data2 , newData]) => {
       const filteredData = data1.filter(item => item.id === model.id);
      
    }

    // Observable
    getNewData() {
      return this.API('GET', `data`)
    }

Why you changed your question?

now our answers are not correct - do not do so

UPDATED ANSWER:

forkJoin(
 this.method1(),
 this.method2()
)
 .pipe(
   map(([data1, data2]) => {
     const filterData = [data1, data2]; // here will be some filtereing
     return filterData;
   }),
   mergeMap(filteredData => {
     // here you can append your filterData
     return this.getNewData(filteredData);
   })
 )
 .subscribe(console.log);

   getNewData(filterData) {
     return this.API('GET', filterData)
   }

DEMO: https://stackblitz.com/edit/typescript-j7rrwl?file=index.ts

1 Comment

If my answer helps you, you can mark it as correct

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.