ForkJoin Observable failing to trigger events

Having an issue with implementing forkJoin on two Observables in my code. Despite directly subscribing to them yielding a response, the forkJoin function doesn't seem to be triggering. Any suggestions on what might be causing this?

private data$: Observable<any[]>;
private statuses$: Observable<any[]>;
private queryStream = new Subject<string>();    

....

this.data$ = this.queryStream
    .startWith('')
     .flatMap(queryInput => {
            this.query = queryInput
            return this._companyService.getCompanies(this.queryRequired + ' ' + this.query, this.page, this.sort);
                })
            .share();
    
...

Observable.forkJoin(this.statuses$, this.companies$)
            .subscribe(res => {
                console.log('forkjoin');
                this._countStatus(res[0], res[1]);
            });


// This shows arrays in the console...

this.statuses$.subscribe(res => console.log(res));
this.companies$.subscribe(res => console.log(res));

// In the console
Array[9]
Array[6]

Answer №1

forkJoin only emits when all inner observables have finished processing. For a similar behavior to forkJoin but with just one emission from each source, you can use combineLatest combined with take(1)

combineLatest(
  this.statuses$,
  this.companies$,
)
.pipe(
  take(1),
)
.subscribe(([statuses, companies]) => {
  console.log('forkjoin');
  this._countStatus(statuses, companies);
});

Once both sources emit their values, combineLatest will trigger an emission, and take(1) will immediately unsubscribe after that.

Answer №2

One common issue that arises with the forkJoin function is that it necessitates all source Observables to emit at least one item and for each of them to complete.

Put simply, if neither this.statuses$ nor this.companies$ emit any items until they both reach completion, then the forkJoin will not emit anything.

this.statuses$.subscribe(
    res => console.log(res),
    undefined,
    () => console.log('completed'),
);

Answer №3

After encountering issues with the forkJoin method, I was able to successfully address my problem by using the code snippet below. By leveraging the power of mergeMap, you can effectively map the results of the outer subscription to the inner subscription and handle them according to your needs.

this.data$.pipe(
    mergeMap(source => this.details$.pipe(
        map(inner => [source , inner])
        )
    )
).subscribe(([result1 , result2]) => {
    console.log(result1 , result2);
})

Answer №4

To optimize the execution of asObservable()-like observables, simply add .pipe(take(1)) as a pipe.

forkJoin({
    l0: this._svc.data$.pipe(take(1)),
    l1: this._api.getLogman1(),
    l2: this._api.getLogman2(),
    l3: this._api.getLogman3(),
})
    .pipe(
        takeUntil(this._unsubscribeAll),
    )
    .subscribe(result => {
        console.log(result);
    });

Answer №5

In contrast to subscribe, forkJoin is unable to work in the same way because it does not function based on events.

Subscribe reacts to a next or completed event, whereas forkJoin only triggers once all observables have completed.

Unlike combineLatest, which fires when all observables emit a next or completed event, forkJoin will only fire when all observables emit a completed event.

Hence, if your observables are emitting next events, the code you posted won't work; however, the following code should be effective:

combineLatest([this.statuses$, this.companies$])
        .subscribe(res => {
            console.log('combineLatest');
            this._countStatus(res[0], res[1]);
        });

Referencing the rxjs documentation, for your scenario, combineLastest is the preferred method: https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin

Documentation for combineLatest: https://www.learnrxjs.io/learn-rxjs/operators/combination/combinelatest

Further information on Observables and the various events they can trigger: https://rxjs.dev/guide/observable

Answer №6

The solution I discovered was using the combineLatest operator!

Answer №7

When using Observable.forkJoin() in Angular, we can combine multiple HTTP requests into a single observable. For example, we can fetch users and customers data simultaneously by calling _someService.getUsers() and _someService.getCustomers().

Here is an example implementation:

Observable.forkJoin([
  _someService.getUsers(),
  _someService.getCustomers(),
])
  .subscribe((data: [Array<User>, Array<Customer>]) => {
    let users: Array<User> = data[0];
    let customer: Array<Customer> = data[1];
  }, err => {
  });

// someService
getUsers(): Observable<User> {
  let url = '/users';
  return this._http.get(url, headers)
    .map(res => res.json());
}

getCustomers(): Observable<Customer> {
  let url = '/customers';
  return this._http.get(url, headers)
    .map(res => res.json());
}

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

Angular Pause until the variable is ready

I am in the process of developing a new web application service. The first step involves obtaining a token through the rest API. Once this token is obtained, it needs to be sent as a header to retrieve additional information. The issue I'm facing is ...

What is the best way to transfer two distinct states from my ngrx effect to my service function?

I am encountering a dilemma with my effects function, where I am attempting to pass data from a dispatched action and a separate selector to a service function. However, I am finding myself confused by the RXJS syntax and suspect that I may not be mapping ...

Quirky happenings in Typescript

TS Playground function foo(a: number, b: number) { return a + b; } type Foo1 = typeof foo extends (...args: unknown[]) => unknown ? true : false; // false type Foo2 = typeof foo extends (...args: any[]) => unknown ? true : false; // true What is ...

Assign a specific HTML class to serve as the container within an Angular directive

Is there a way to dynamically add and set an HTML class using an Angular directive with a parameter? Let's consider a scenario where we have a div with an existing class but no directive: <div class="myClass"></div> Now, if we w ...

There was a parsing error due to encountering an unexpected reserved word 'interface' in the code, as flagged

I'm encountering an issue with my code when trying to utilize Props. The error message I'm receiving is "Parsing error: Unexpected reserved word 'interface'. (3:0)eslint". This project is being developed using next with TypeScript. Er ...

Typescript's tree-pruning strategy design for optimization

I've been working on developing a library that enforces the use of specific strategies for each target. The current structure I have in place is as follows: [Application] -> contains -> [player] -> contains -> [renderer] In the current s ...

Troubleshooting a unique problem with custom mat errors in Angular File Upload

In my Angular 5 app, I have a file upload form where I need to show a custom error message if the file format does not match certain criteria: The error message that should be displayed to the user is: "Only PDF, Excel, PowerPoint, or Audio (wav and wmv) ...

Tips on how to integrate a Twitter timeline into an Angular 6 application

I've been trying to integrate a Twitter timeline into an Angular 6 application, but I have yet to find a satisfactory solution. Here's what I've attempted so far: Inserted the Twitter generated code from 'publish.twitter.com' int ...

Issue: Failed to access the 'setDir' property of an undefined object

Greetings, I am a newcomer to Ionic/Angular and have been facing a particular issue for over 20 days now. I have created a small app and would like to implement multi-language support with both RTL and LTR directions. I followed the documentation provided ...

Guide to summing the values in an input box with TypeScript

https://i.stack.imgur.com/ezzVQ.png I am trying to calculate the total value of apple, orange, and mango and display it. Below is the code I have attempted: <div class="row col-12 " ngModelGroup="cntMap"> <div class="form-group col-6"> ...

I have installed npm globally, but for some reason, I keep getting an error prompting me to reinstall it for every new Angular

Recently, I started delving into Angular 4. Following a tutorial, I installed nodejs, then the angular 4 cli, and created my project to begin working. Everything seemed fine until I tried running a local server using ng serve --open, which resulted in the ...

The date displayed in the table is incorrectly showing 04 instead of 03 when using the pipe

{{element.createdAt | date: 'MM/dd/yyyy h:mm'}} why are the dates in the database all showing as 23 but some values are displaying as 24? Please confirm. The first two values created in the db show a createdAt time of 3, but the table is showing ...

What steps can I take to fix the Error: Module not found "." in Ionic 3?

While working on building an ionic project for production, everything runs smoothly in debug mode. However, when I try to serve it, no errors appear. But when attempting to build or run android, two different errors are thrown. Despite checking in IDEs lik ...

Turn off the incorrect TypeScript error detection

After setting up 'interact.js' using jspm and npm for TypeScript compatibility, I am encountering errors in my code: import { interact } from 'interact.js/interact' // ==> typescript error: TS2307: Cannot find module 'interact. ...

Troubleshooting issue with React and Material UI Table pagination display

Issue with Material UI Table Display When Changing Pages When receiving an array of Artist Objects through props to create a checklist table, I encounter some display issues. The table works fine initially, but when changing pages or sorting, more rows th ...

Go through a collection of Observables and store the outcome of each Observable in an array

As a newcomer to Angular and RxJS, I am facing a challenge with handling social posts. For each post, I need to make a server call to retrieve the users who reacted to that post. The diagram linked below illustrates the process (the grey arrows represent r ...

What is the proper way to compare enum values using the greater than operator?

Here is an example enum: enum Status { inactive = -1, active = 0, pending = 1, processing = 2, completed = 3, } I am trying to compare values using the greater than operator in a condition. However, the current comparison always results in false ...

Can someone help me troubleshoot why findMany is not functioning properly within my generic Prisma service? Additionally, what steps can I take

I'm currently tackling a project that involves creating a versatile service to display all entries from any Prisma model within my application. My approach utilizes TypeScript in conjunction with Prisma, aiming to dynamically pass a Prisma model to th ...

Transform "<Mutation>" to useMutation

In my removeUser page, I have implemented a < Mutation > and handled errors using the submitForm() function. The initial code worked perfectly: export default function RemoveUserPage() { const [isSubmitted, setIsSubmitted] = useState(false); con ...

The specified property 'nodeName' is not recognized within the data type 'EventTarget'

In the code snippet below, we are checking whether the user is interacting with an input field, textarea, or contenteditable element. If any of these conditions are met, we should clear out the keys array and stop the script execution. let keys: any[] = [] ...