Anticipating the outcome of various observables within a loop

I'm facing a problem that I can't seem to solve because my knowledge of RxJs is limited.

I've set up a file input for users to select an XLSX file (a spreadsheet) in order to import data into the database. Once the user confirms the file, various validations are performed on the document before insertion to prevent any issues.

The file is scanned and checked line by line. However, one of my verification processes is causing a dilemma. I need to utilize a database procedure to verify the existence of certain data in the database. The issue arises when the query returns an observer, causing my for loop to iterate through the entire file even before receiving the query result. The console displays 'Import finish' before completing the necessary checks.

I am wondering if there's a way to pause the loop until I receive the result from the subscribe function, or if I can let the loop complete and then finalize the import once all results are obtained.

Component:

importObjectives(): void {
    // Code snippet
}

Store Wallet:

checkWallets(xlsx: XLSXObjective, lineError): Observable<any> {
    // Code snippet
}

Service Wallet:

checkWallets(xlsx: XLSXObjective): Observable<any> {
    // Code snippet
}

Any assistance would be greatly appreciated. Thank you, and please excuse any language errors.

Answer №1

Utilize Observable.forkJoin to create a loop for observables, allowing you to wait for all data to be received from multiple observables.

Observable.forkJoin is ideal when you need to synchronize the responses from multiple HTTP calls.

If you are unsure about the data returned by your HTTP calls, here's a simple example:

    loadedCharacter: {};
  constructor(private http: HttpClient) { }

  ngOnInit() {
    let character = this.http.get('https://swapi.co/api/people/1');
    let characterHomeworld = this.http.get('http://swapi.co/api/planets/1');

    forkJoin([character, characterHomeworld]).subscribe(results => {
      // results[0] contains character data
      // results[1] contains character homeworld data
      results[0].homeworld = results[1];
      this.loadedCharacter = results[0];
    });

Answer №2

Here's my approach:

const observableTasks = [];

fetchDataFromExternalSource(): void {
    if (this.dataFile) {
        if (["xlsx","xls","csv"].includes(this.dataFile.name.split('.').pop())) {
            if (typeof (FileReader) !== 'undefined') {
                const reader = new FileReader();

                reader.onload = (event: any) => {
                    let fileDataArray = new Uint8Array(event.target.result);
                    let workbook: XLSX.WorkBook = XLSX.read(fileDataArray, { type: 'array' });
                    let sheetName: string = workbook.SheetNames[0];
                    let worksheet: XLSX.WorkSheet = workbook.Sheets[sheetName];
                    let parsedData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });

                    parsedData.shift();
                    for(var rowData of parsedData) {
                        var rowLineNumber = parsedData.indexOf(rowData) + 2;
                        // Additional validations...
                        observableTasks.push(this.dataProcessingService.checkData(this.XLSXObjective, rowLineNumber))
                    }

                    forkJoin(observableTasks).subscribe(dataResults => {
                      if(this.errors.length > 0) {
                          console.error("Errors encountered:");
                          console.error(this.errors);
                      } else {
                          console.log("Data import completed successfully");
                      }
                    }
                    this.dialogReference.close();
                };
                reader.readAsArrayBuffer(this.dataFile);
            }
        } else {
            console.error("File format not supported");
            this.dialogReference.close();
        }
    } else {
        console.error("No data file provided");
        this.dialogReference.close();
    }
}

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

AngularYelp: Node Integration for Enhanced Functionality

Embarking on a new learning journey here, so please bear with me... Discovered node-yelp while browsing Yelp's API docs. Check it out here. // Request API access: http://www.yelp.com/developers/getting_started/api_access var Yelp = require('yel ...

Avoid triggering onClick events on all rows when clicking, aim for only one row to be affected per click

I have a unique situation where I have a table containing rows with a button in each row. When this button is clicked, it triggers an onClick event that adds two additional buttons below the clicked button. The Issue: When I click on a button, the onClick ...

Troubleshooting Angular 2 routerLink functionality issues

I have gone through all the tutorials and still can't figure out what I am doing wrong. AppModule : import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } fr ...

When the first argument is missing, using a recursive constraint default can result in the incorrect inference of the second argument, especially when both arguments share the same generic

Currently, I am developing a TypeScript implementation of a recursive binary search tree (BST) data structure using generic constraints. In order to establish a default for the recursive generic variable T without directly using it in the default declarati ...

Troubleshooting the issue of Angular2's http withCredentials not functioning as expected

Utilizing Angular2's HTTP module, I am sending HTTP requests. Once a user logs in, the backend server creates a cookie session which is then used by the frontend to send subsequent requests. The Angular code snippet is outlined below: get(url: string ...

Determine the output type of a function in Typescript using an input value specified by an enum

I am currently saving settings to local storage and want to be able to input responses when retrieving (and possibly inserting) values from/to the storage. After researching, it seems that using function overloading is the best approach. Here is what I ha ...

Cricket score update features on the client side

Looking for assistance with client-side code development! I am currently working on an Android application using Ionic that involves live cricket scores. I have purchased a cricket API and understand how to connect to it using Node.js on the server side. ...

The instanceof operator does not recognize the value as an instance and is returning false, even though it

Is there a method to verify the current instance being used? This is what I am logging to the console: import { OrthographicCamera } from 'three'; // Later in the file: console.log(camera instanceof OrthographicCamera, camera); and the result ...

Is there a specific type of function missing in Typescript?

I am facing a challenge in converting an existing JavaScript code to Typescript. The original javascript code is as follows: object.getsomething( function(err, result) { // async }); I am confused about how to properly type the parameter "function(er ...

"Encountering an error when trying to access undefined property in templates

The content displayed in my component template is not what I expected when using @Output to pass an object from a parent container. While attempting to bind {{selectedMovDetail|json}} in the template, the output shows as { "name": "The Walking Dead","rati ...

How do @material-ui/core and @types/material-ui interact with each other?

Exploring a sample project that utilizes material-ui. Upon inspecting the package.json file, I noticed the inclusion of the following packages: { ... "dependencies": { "@material-ui/core": "^1.4.1", ... }, "devDependencies": { "@types ...

Trouble of VueJs array data property with .includes() in search for integer value

I'm struggling to figure out how to check if an integer value is already stored in the data property of array type. The Observer type property always returns false when I ask: this.selected.includes(value) Below is my complete example - I cast the va ...

Exploring the power of makeStyles in Material UI when combined with TypeScript

I am currently in the process of converting a JavaScript template to Typescript. Here is an example of my accordionStyle.ts file: import { primaryColor, grayColor } from "../../material-dashboard-pro-react"; const accordionStyle = (theme?:an ...

Encountering type errors in NextJS with TypeScript

I am facing an issue while trying to run this function: "use server"; export const addProduct = async (formData: FormData, imageUrl: string) => { const productName = formData.get("productName")?.toString(); const description = f ...

Disable the default animation

Is there a way to disable the default animation of the Select label in my code snippet below? export default function TicketProfile(props: any) { return ( <Container> <FormControl sx={{ ml: 1, mr: 1, minWidth: 220 }}> <Inp ...

Perform a delayed evaluation of the length of the @Input() array

In my Component, I am utilizing an @Input() ids: string[] = []; variable to check if the length equals 1 in the DOM. <mat-expansion-panel *ngFor="let id of ids" [expanded]="ids.length === 1"> ... </mat-expansion-panel> However, when I append ...

Mastering the art of Typescript typing

I am attempting to start the REST server for an Aries agent as outlined here: import { startServer } from '@aries-framework/rest' import { Agent } from '@aries-framework/core' import { agentDependencies } from '@aries-framework/nod ...

Pagination problem arises when sorting through items

I am facing an issue with filtering items on different pages of my React website. The problem I encounter is that the filtering functionality only works on the initial page where the data is loaded. Code: CustomersEpolicyPage.tsx import React, {useEffect ...

Tips for specifying a variable as a mandatory key attribute within an array

Is there a way to dynamically determine the type of key attribute in an array? const arr = [ { key: 'a' }, { key: 'b' }, { key: 'c' }, ]; type key = ??? // Possible values for key are 'a', 'b', or &a ...

Error Message: The Query<DocumentData> type cannot be assigned to the DocumentReference<DocumentData> parameter

Currently, I am attempting to execute a query against Firestore data. Here is my code snippet: import { collection, getDoc, query, where } from "firebase/firestore"; import { db } from "../../utils/firebaseConfig"; const getQuery = a ...