Question: I need wait for two requests (observables) and do some things.
What i need:

1. Wait for requests (observables) end
2. If one of them failed - display one error
3. If both of them failed - display second error
4. If first success - do some things
5. If second success - do some things

i can combine 4 and 5 if that matter for errors handling.

I tried to use `forkJoin` but it fails at all if one of requests failed.  

I tried to use `concat` but it works the same as `forkJoin`  

I tried to use `combineLatestWith` but it doesn't display errors at all as `combineLatest`  

Finally i tried to use next:

```
const firstRequest$ = this.doFirstRequest(searchRequest);
const secondRequest$ = this.doSecondRequest(searchRequest);
combineLatest([firstRequest$, secondRequest$]).subscribe(([res1, res2]) => {
  console.log(res1, res2);
}, err => {
  console.log(err);
});

```

and now i got only both success results and didn't get any error
What im missing?

Answer: 
catch your errors at the request level and transform them into something usable:

```
const firstRequest$ = this.doFirstRequest(searchRequest).pipe(
  catchError(error => of({error})) 
);
const secondRequest$ = this.doSecondRequest(searchRequest).pipe(
  catchError(error => of({error}))
);
forkJoin([firstRequest$, secondRequest$]).subscribe(([res1, res2]) => {
  if (res1.error && res2.error) {
    // both failed
  } else if (res1.error || res2.error) {
    // one failed
  }
  if (!res1.error) {
    // req 1 success 
  }
  if (!res2.error) {
    // req 2 success
  }
  // whatever you need to do now that they're both done
}, err => {
  // can't get here now
});

```
1. You need to use `forkJoin` for this use case, See [ForkJoin docs](https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin).
2. Add `catchError` operator to the first stream to handle the first request
3. Add another `catchError` operator to the second stream to handle it
4. Add `tap` operator to the first stream 1
5. Add another `tap` operator to the first stream 2

```js
const firstRequest$ = this.doFirstRequest(searchRequest).pipe(
  tap(() => {
    // DO SOMETHING STREAM 1 REGARDLESS OF STREAM 2
  }),
  catchError((e => {
    console.error('Error from stream 1', e);
    return of(null);
  });
);

const secondRequest$ = this.doFirstRequest(searchRequest).pipe(
  tap(() => {
    // DO SOMETHING STREAM 2 REGARDLESS OF STREAM 1
  }),
  catchError((e => {
    console.error('Error from stream 2', e);
    return of(null);
  });
);

forkJoin([firstRequest$, secondRequest$]).subscribe(([res1, res2]) => {
  console.log('All done');

  if (res1) {
    // DO SOMETHING STREAM 1 AFTER ALL STREAMS ARE DONE
  }

  if (res21) {
    // DO SOMETHING STREAM 2 AFTER ALL STREAMS ARE DONE
  }
});

```