When you subscribe to a forkJoin, you will receive an error notification

Trying to determine when all my observables have returned their values is a challenge I'm facing. Here's my approach after including

import { Observable } from 'rxjs/Rx';
:

    let observables:any[] = [];

    observables.push(this.getValue1().subscribe((value1)=> {
        // Do something with value1
    }));
    observables.push(this.getValue2().subscribe((value2)=> {
        // Do something with value1
    }));

    Observable.forkJoin(observables).subscribe(
        data => {
            console.log('initialized');
        },
        err => console.error(err)
    );

The values are passed through observer.next(valueX);

An error message keeps popping up:

TypeError: source.subscribe is not a function
. Can someone point out what I might be doing incorrectly?

Update: Below is how I construct my getValues()

getValue1(): any {
    return new Observable(observer => {
        this.asyncFunc(arg1, (err, value1)=> {
            observer.next(value1);
        }
    }
}

Answer №1

When using forkJoin, it's important to note that you should pass in Observables instead of Subscriptions. Calling subscribe on an Observable signifies the completion of the pipeline, resulting in a cancellation primitive (i.e., Subscription) being returned.

The subscribe block should only be used once at the end. If you need to perform intermediate processing in forkJoin, remember that it accepts an optional selector argument as well.

let observables:any[] = [];

observables.push(this.getValue1());
observables.push(this.getValue2());

Observable.forkJoin(observables, ([value1, value2]) => {
  //Do something with value1 and value2
  return [value1, value2];
}).subscribe(
    data => {
        console.log('initialized');
    },
    err => console.error(err)
);

Edit

Since forkJoin waits for all Observables to complete, you must ensure the sources are completed (and handle any errors). Therefore, your getValue1 function should look like this:

getValue1(): any {
    return new Observable(observer => {
        this.asyncFunc(arg1, (err, value1)=> {
            if (err)
              return observer.error(err);

            observer.next(value1);
            observer.complete();
        }
    }
}

An alternative approach is to use the bindNodeCallback operator.

This would simplify the code:

this.getValue1 = Observable.bindNodeCallback(this.asyncFunc);
this.getValue2 = Observable.bindNodeCallback(this.asyncFunc);

Allowing you to call these functions uniformly:

let observables:any[] = [this.getValue1(), this.getValue2()];

To update progress on completion, you can utilize a secondary stream when using bindNodeCallback.

// Incorporate length into the stream
Observable.of(observables.length)
          .flatMap(len => Observable.merge(observables), 
                   (len, _, inner, outer) => outer / len * 100)
          .subscribe(percentCompleted => /*Update progress bar*/);

If opting not to use bindNodeCallback, you'd need to do more work since each stream is cold. You can make them ConnectableObservables to mitigate this issue.

// Convert to ConnectableObservables
let observables:any[] = [this.getValue1().publishLast(), this.getValue2().publishLast()];

// Set up additional streams
Observable.of(...);

Observable.forkJoin(...);

// Activate Observables
observables.forEach(c => c.connect());

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

Dealing with missing image sources in Angular 6 by catching errors and attempting to reset the source

When a user adds a blob to my list, sometimes the newly added image is still uploading when the list is refreshed. In this case, I catch the error and see the function starting at the right time: <img src="https://MyUrl/thumbnails/{{ blob.name }}" widt ...

In Angular 7, where can the controller be found within its MVC architecture implementation?

From what I understand, Angular adheres to the MVC architecture. In the components, there is a .ts file which serves as the model and a .html file for the view, but my question is: where is the controller located? ...

Converting a string to an HTML object in Angular using Typescript and assigning it to a variable

I am facing an issue with passing HTML content from a service to a div element. I have a function that fetches HTML content as a string from a file and converts it into an HTML object, which I can see working in the console. However, when trying to assign ...

The functionality of GetStaticProps with Typescript is only operational when defined as an arrow function, rather than a function

The documentation for GetStaticProps in NextJs explains it as a function declaration. When trying to add types to it, the following code snippet results: export async function getStaticProps(): GetStaticProps { const db = await openDB(); const fa ...

The error "Prop does not exist on type 'PropsWithChildren'" occurs when attempting to dispatch an action with react-redux

When attempting to dispatch the action, I am encountering this error: The error message reads: Property 'fetch_feed_loc' does not exist on type 'PropsWithChildren<{ onSubmitForm: any; }>'. Another error states: Property &apos ...

Using Angular 6 pipes can simplify observable operations by eliminating the need for explicit typing

Recently, I upgraded my application from Angular5 to 6. Upon completing the update, I proceeded to migrate to rxjs6, which resulted in a change in my code where I was utilizing the takeWhile method. As a result, in order to subscribe to a service, my code ...

Is it possible to selectively mock certain components of an external module using jest?

I am totally new to using Jest, especially in regards to unit tests, and I am struggling to write a test for a specific scenario. I know that you can mock an external module like this.. jest.mock('@organisation/library', () => ({ Database: j ...

The element at index '0' is not defined for the data type 'number | [number, number]'

In my current project, I have a component named ComponentA which has a defined interface. Here is the snippet of the interface: interface A1 { isSingle: true; value: number; } interface A2 { isSingle: false; value: [number, number]; } exp ...

When a property is removed from a variable in an Angular Component, it can impact another variable

During the iteration of the results property, I am assigning its value to another property called moreResults. After this assignment, I proceed to remove array elements from the testDetails within the moreResults property. However, it seems that the remova ...

Does the router navigate function instantly update the router URL?

I'm testing whether the navigate function will immediately alter the router URL upon execution. this.router.navigate(['/home/products']); if (this.router.url.includes('/home/products')) console.log('URL has been changed&apos ...

Incorporating a swisstopo map from an external source into an Angular

I am looking to integrate a swisstopo map into my angular 8 app. As I am new to angular, I am unsure how to include this example in my component: I have tried adding the script link to my index.html file and it loads successfully. However, I am confused a ...

Trouble with React Context State Refreshing

Exploring My Situation: type Props = { children: React.ReactNode; }; interface Context { postIsDraft: boolean; setPostIsDraft: Dispatch<SetStateAction<boolean>>; } const initialContextValue: Context = { postIsDraft: false, setPostIs ...

What benefits does a bundler offer when releasing packages on npm?

After working with Node.js for many years, I recently ventured into publishing my first Node.JS package for a wider audience. Feeling lost at the beginning, I turned to Google for guidance on how to do this specifically for typescript and stumbled upon thi ...

The SDK directory for TypeScript 1.3 in Visual Studio 2013 does not include the necessary tsc.exe file

Exciting news! Typescript v1.3 has been officially announced today. To fully utilize this update, I quickly installed the power tools update for VS2013. Upon completion of the installation, my Visual Studio environment now recognizes the "protected" keywo ...

Using rxjs takeUntil will prevent the execution of finalize

I am implementing a countdown functionality with the following code: userClick=new Subject() resetCountdown(){this.userClick.next()} setCountDown() { let counter = 5; let tick = 1000; this.countDown = timer(0, tick) .pipe( take(cou ...

What is the best method for transitioning to a new page in React Native using Ignite Bowser?

Recently I ventured into the world of React Native with Ignite Bowser. My current project involves building a React Native app using Ignite Bowser. At the start of my app, there's a welcoming screen that pops up. It features a 'continue' bu ...

Error: In Typescript, it is not possible to assign the type 'false' to type 'true'

Currently, I am exploring Angular 2 and encountered a situation where I set the variable isLoading to true initially, and then switch it to false after fetching required data. However, upon executing this process, I encountered the following error message: ...

What are the steps to set up a dictionary with predetermined values?

My task is to create a pre-defined dictionary where the key represents a city and the value is an array of zones in that city. Here is my attempt: export const cityToZone: { [city: string]: Array<string> } = [ {city:'New York', [&apos ...

A guide on incorporating and utilizing PhotoSwipe in Aurelia / Typescript applications

I've been attempting to integrate PhotoSwipe into my Aurelia project, but I'm struggling to get it working. Within my aurelio.json file under bundles, I've included: { "name": "photoswipe", "path": "../node_modules/photoswipe/dist/ ...

Distributing utility functions universally throughout the entire React application

Is there a way to create global functions in React that can be imported into one file and shared across all pages? Currently, I have to import helper.tsx into each individual file where I want to use them. For example, the helper.tsx file exports functio ...