Tips for properly waiting for forkJoin.subscribe in order to access the returned values

Continuing from this previous post, I've decided to create a new post since the question in this one is different.

Query - How can I ensure that the forkJoin operation completes before executing other business logic?

Below is the Code Snippet

export interface indexLogic {
  [id: number]: Detail;
}
async ngOnChanges(){
    await getData(); 
    // Need to guarantee that the following method only runs 
    // after this.indexLogic has been populated.
    await useInformationReceivedFromgetData(); 
}
async getData(){
  getInformations().subscribe(
    informations => {
      let subs = [];
      for (const information of informations) {
         subs.push(getOtherDetails(information.id).pipe(
            map(data => ({ id: information.id, data })) // <---
         ));
      }
        this.indexLogic = [];
          forkJoin(subs).subscribe(objects => {           
             objects.forEach(({id, data}) => { this.indexLogic.push({[id]:data}) });
          });
       }    
    );
}

Answer №1

Instead of converting to a Promise, it is unnecessary in this case.

    runningParallel(subs).subscribe(results => {           
         results.forEach(({key, value}) => { this.updateList.push({[key]:value}) });
          // Add your code or function calls here
          this.performAction()
      });

Answer №2

Given that the data stored in indexLogic is derived from asynchronous actions and requires immediate reaction to value changes, it is best to treat indexLogic as an asynchronous entity. Storing this information as an Observable allows for easy subscription and handling of updates.

Take a look at the code snippet below (referring to details discussed in your previous post)

interface Detail {
  id: string;
}
interface IndexLogic {
  [id: string]: Detail;
}

export class InformationComponent {
  indexLogic$ = new Observable<IndexLogic[]>();

  ngOnInit(): void {
    getInformations()
      .pipe(
        mergeMap((informations) => {
          return forkJoin(
            informations.map(({ id }) =>
              getOtherDetails(id).pipe(map((detail) => ({ [id]: detail }))),
            ),
          )
        }),
      )
      .subscribe((indexLogic) => {
        useInformationReceivedFromgetData(indexLogic)
      });
  }
}

In addition, I have repositioned the code within the ngOnInit method, which may be more suitable for initializing data retrieval in your Component rather than using ngOnChanges.

Furthermore, note that there is no usage of the async keyword in the provided code. While async/await is useful in JavaScript, leveraging Observables from RxJs eliminates the need for async/await, ensuring a consistent approach towards managing asynchronous tasks.

Answer №3

One way to guarantee the completion of the forkJoin operation before proceeding with other business logic is by utilizing the toPromise method and awaiting the outcome.

export interface indexLogic 
{
    [id: number]: Detail;
}

async ngOnChanges() 
{
    await this.getData();
    await this.useInformationReceivedFromgetData();
}

async getData() 
{
    const informations = await getInformations().toPromise();
    const subs = [];
    for (const information of informations) 
    {
        subs.push(getOtherDetails(information.id).pipe(
        map(data => ({ id: information.id, data }))
        ));
     }

     this.indexLogic = [];
     const objects = await forkJoin(subs).toPromise();
     objects.forEach(({ id, data }) => 
     {
          this.indexLogic.push({ [id]: data });
     });
}

async useInformationReceivedFromgetData()  
{
   // Business logic that relies on this.indexLogic being populated
}

In the modification made to the getData method, the toPromise method is now utilized instead of directly subscribing to the observable. This adjustment enables you to wait for the outcome and ensure that all asynchronous operations are concluded before proceeding. Additionally, the forkJoin operation has been transformed into a promise using toPromise to enable it to be awaited. The resulting data is stored in the objects variable, allowing the business logic within the useInformationReceivedFromgetData method to be executed securely once the this.indexLogic array has been populated.

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

Utilizing string interpolation within the parameters of an AJAX call

I have a locale variable that can hold values such as en, fr, or es. The goal is to include this locale key in an AJAX request as part of the data parameter. let locale = "en"; let name = "example"; $.ajax({ url: "/path", method: "PUT", data: {chara ...

Tips for executing a <script> whenever the properties of a component are modified

Can I automatically run a <Script/> every time the props of a react/nextjs component change? I'm currently converting markdown files to HTML using marked and, before rendering the HTML, I want to include a [copy] button on each <pre> bloc ...

CAUTION: Attempted to load angular multiple times while loading the page

I encountered a warning message while working on my project, causing errors in calling backend APIs due to duplicate calls. Despite attempting previously suggested solutions from the forum, I am stuck and seeking assistance. Can anyone provide guidance? Be ...

Looking to conduct date comparisons within angular-ui-grid?

I'm currently working on an application that utilizes angular-ui-grid to display form data. One issue I'm facing is how to compare the submission date obtained from an API call with the current date within ui-grid, in order to calculate the numbe ...

Is it possible to trigger the execution of two functions simultaneously by using onClick in JavaScript?

I currently possess: one = () => { //perform a task } two = () => { //execute an action } <div> <button onClick={/*this.one, this.two (it doesn't function)*/}>Go</button> </div> Is there a way to invoke two f ...

"Unable to modify the color of an SVG element within a FabricJS canvas

I am attempting to modify the fill of an SVG path that is located within a fabric.js canvas. https://i.sstatic.net/047kl.png Here is the function I am using: function changeColor(material) { console.log(svgGroup[0].fill) console.log(material); ...

implement some level of control within the ngFor directive in Angular

For instance, let's say I have an ngfor loop: <ng-container *ngFor="let setting of settings | trackBy: trackById"> <button mat-button [matMenuTriggerFor]="menu">Menu</button> <mat-me ...

Add some flair to your list by animating the text within it

My goal is to add animation to the text within the list. Below is the code snippet: <div id="about" class="row section"> <div class="col-sm-8"> <h2 style="color:black;">About me!</h2> <ul> <li > ...

Authentication of local users with NodeJS using passportJS and MySQL

I am having trouble identifying the mistake in this code snippet: Undefined "Unknown user" passport.use(new LocalStrategy( function(username, password, done) { process.nextTick(function () { findByUsername(username, function(err, user) { ...

issue with AngularJS model not initially binding to select dropdown

I am facing an issue with a select dropdown in my code. I am using ng-repeat to populate the dropdown like this: <select ng-model="tstCtrl.model.value" required> <option ng-repeat="option in tstCtrl.myOptions" value="{{option.a}}">{{option.b ...

The process of encoding Point of Sale (POS) data as application/x-www-form-urlencoded

Can anyone provide guidance on how to correctly POST a URL encoded as application/x-www-form-urlencoded? I have all the necessary variables for the API suggestion below, but I'm struggling with posting it correctly. Thank you in advance for your help ...

When the client initiates, Meteor gets a head start

Can you explain why, on the client side, the variable init in if(init) is evaluated to be true even before init = true is called and when no new documents are added to the Orders collection? As a result, the query.observe function returns all documents ret ...

Trouble with running dynamically injected <SCRIPT> tags in Firefox version 47.0

After making an AJAX call, I receive an HTML snippet that looks like this: <SCRIPT src="..." type="text/javascript"></SCRIPT> <SCRIPT type="text/javascript"> function showForumGrid() { ... }; function f() { ...} </SCRIPT> < ...

Using addClass and fadeIn simultaneously when hovering over an element

After writing JavaScript code that utilizes the JQuery library to swap classes on hover, I noticed that the transition between background images was quite abrupt. The code functions as intended, but I would prefer to incorporate a fadeIn and fadeOut effect ...

Having trouble choosing elements with angular.element within ng-repeat loop

In my HTML code, I am using an ngRepeat element: <ol id="animationFrame"> <li ng-repeat="animationImage in animationImages" ng-repeat-listener> <img ng-src="{{animationImage.src}}" id="{{animationImage.id}}"> </li> </ol& ...

transform the outcome of a $lookup operation into an object rather than an array

When performing a $lookup from a _id, the result is always 1 document. This means that I would like the result to be an object instead of an array with one item. let query = mongoose.model('Discipline').aggregate([ { $match: { ...

Removing the final element within a nested array: a step-by-step guide

let originalArray=[ [ "Test1", "4", "160496" ], [ "Test2", "6", "38355" ], [ "Test3", "1", "1221781" ], [ " ...

What is the proper method for passing arguments to a function?

I'm facing an issue with a function in nodejs that uses res.execSync with multiple parameters. More information can be found here: https://github.com/xdenser/node-firebird-libfbclient The function format is as follows: function execSync(param1, ...

jQuery compatible JavaScript plugin

Currently, I am in the process of developing a JavaScript plugin. My goal is for it to make use of jQuery functionalities, while also gracefully degrading if jQuery is not present on the page. For instance, jQuery users would initiate a slideshow by calli ...

The issue at hand is that the Mongo Atlas model is in place, but for some reason,

https://i.sstatic.net/4m2KT.pngI recently delved into using Next.js and I am a newcomer to backend technologies. I have successfully established a connection with MongoDB Atlas using Mongoose, however, the user object data from the post request is not be ...