When using a typescript subscription to collect data from an API, the information is stored in an array. However, only one piece of data can be

I have implemented a method to fetch data from an API using Angular:

ngAfterViewInit() {
  this.exampleDatabase = new ExampleHttpDatabase(this._httpClient);
  var href = '/schuhe-store/status';

  if (environment.production === false) {
    href = 'https://sales.dailysshop.com/schuhe-store/status';
  }

  for (var val of this.dataArray) {
    const requestUrl = `${href}?type=${val}`;

    this._httpClient
      .get<StatusInterface>(requestUrl)
      .pipe(
        map((data) => {
          return data;
        })
      )
      .subscribe(
        (data) => {
          this.dataResults[val] = data;
          console.log(this.dataResults[val]);
        },
        (error) => {
          const dialogConfig = new MatDialogConfig();

          if (error.status == 404) {
            dialogConfig.disableClose = true;
            dialogConfig.autoFocus = true;
            console.log(error.errno);
            this.dialog.open(DialogOverviewExampleDialog, dialogConfig);
          } else if ((error.status = 200)) {
            this.dialog.open(DialogOverviewExampleDialog, dialogConfig);
          }
          this.routeNotRegistered = true;
        }
      );
  }
}

On my HTML page, I am displaying four lines of information using the following code:

            <mat-list-item>
                <mat-icon mat-list-icon>done</mat-icon>
                <div mat-line>Cronjob</div>
                <div mat-line *ngIf='getTimestamp("cron"); else loading;'>Last executed: {{ getTimestamp("cron") | date:'dd.MM.yyyy HH:mm" }} uur</div>
            </mat-list-item>
            <mat-list-item>
                <mat-icon mat-list-icon>done</mat-icon>
                <div mat-line>Export process</div>
                <div mat-line *ngIf='getTimestamp("export"); else loading;'>Last executed: {{ getTimestamp("export") | date:"dd.MM.yyyy HH:mm" }} uur</div>
            </mat-list-item>
            <mat-list-item>
                <mat-icon mat-list-icon>done</mat-icon>
                <div mat-line>Delta export</div>
                <div mat-line *ngIf='getTimestamp("delta"); else loading;'>Last executed: {{ getTimestamp("delta") | date:"dd.MM.yyyy HH:mm" }} uur</div>
            </mat-list-item>
            <mat-list-item>
                <mat-icon mat-list-icon>error</mat-icon>
                <div mat-line>Import process</div>
                <div mat-line *ngIf='getTimestamp("import"); else loading;'>Last executed: {{ getTimestamp("import") | date:"dd.MM.yyyy HH:mm" }} uur</div>
            </mat-list-item>

The function getTimestamp returns the timestamp associated with the provided key:

    getTimestamp(key: string):number|undefined{
        if (this.dataResults[key] && this.dataResults[key]["timestamp"] !== undefined)
            return (this.dataResults[key]["timestamp"]);
        return (undefined);
    }

Currently, only one value is displayed on the HTML page by calling getTimestamp("delta"). How can I display all four values at once?

If anyone could provide guidance or a solution for this issue, I would greatly appreciate it.

Best regards, Henning

Answer №1

const dataValues = ['schedule', 'update', 'remove', 'modify'];


from(dataValues)
  .pipe(
concatMap((action) => {
  const requestLink = `${url}?action=${action}`;
    return this._httpClient.get<ResponseInterface>(requestLink).pipe(map((results) => ({ [action]: results })))
  }
),
    scan((accumulator, currentData) => ({...accumulator, ...currentData}), {})// values will be processed one at a time, if you need the complete object as final result, replace scan with the reduce operator
  )
  .subscribe((response) => {
    console.log(response); // {schedule: ResponseInterface, update: ResponseInterface, ...}
    this.resultsData = response;
  }, 
  errorHandler => {});

Answer №2

Instead of directly subscribing to the sub observables (HTTP calls), a more efficient approach is to use RxJS forkJoin to merge all of them and emit the result using the subscribe method once all sub observables have completed.

Give this implementation a try:

ngAfterViewInit() {
  this.exampleDatabase = new ExampleHttpDatabase(this._httpClient);
  var href = '/schuhe-store/status';

  if (environment.production === false) {
    href = 'https://sales.dailysshop.com/schuhe-store/status';
  }

  if (!this.dataArray?.length) return;

  forkJoin(
    this.dataArray.map((val) => {
      const requestUrl = `${href}?type=${val}`;
      return this._httpClient.get<StatusInterface>(requestUrl).pipe(
        tap((data) => {
          this.dataResults[val] = data;
        })
      );
    })
  ).subscribe(
    () => {
      console.log('DONE!');
    },
    (error) => {
      const dialogConfig = new MatDialogConfig();

      if (error.status == 404) {
        dialogConfig.disableClose = true;
        dialogConfig.autoFocus = true;
        console.log(error.errno);
        this.dialog.open(DialogOverviewExampleDialog, dialogConfig);
      } else if ((error.status = 200)) {
        this.dialog.open(DialogOverviewExampleDialog, dialogConfig);
      }
      this.routeNotRegistered = true;
    }
  );
}

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

Code: Ensuring URL spaces are maintained

In my Angular 4 project, I have a service with a delete API that requires two strings as parameters. Here is an example of how it looks: this.http.delete(this.url + 'api/v1/ReportingService/collectionID/'+ '45902' +'/'+' ...

Utilizing dual functions within the onChange event handler in React

I have a situation where I need to pass a function from a parent component to a child component through the onChange event, as well as another function in the child component to update its own state. How can I achieve this? Parent export function Fruits() ...

Simple steps to transform the "inputs" syntax into the "@Input" property decorator

There's this code snippet that I need to modify: @Component({ selector: 'control-messages', inputs: ['controlName: control'], template: `<div *ngIf="errorMessage !== null">{{errorMessage}}</div>` }) Is the ...

Reference ngFor for Input Validation Template

I'm currently facing an issue with validating input fields within a *ngFor loop. I am struggling to create unique template references for each input field. Basically, I need all input fields to be required on submit unless at least one of them is fill ...

Extract and preserve elements from an ordered array by segregating them into separate arrays of objects using Angular 8

I have an array called arrayReceived containing 15 objects. My goal is to sort and store the first 6 objects with the lowest amount value in a new array called arraySorted. These objects are sorted based on their amount parameter. There may be multiple obj ...

Differentiate between function and object types using an enum member

I'm currently experimenting with TypeScript to achieve narrowed types when dealing with index signatures and union types without explicitly discriminating them, such as using a switch case statement. The issue arises in the code snippet below when at ...

How can I specifically activate the keydown event for alphanumeric and special characters in Angular7?

I am looking to create a keydown event that will be triggered by alphanumeric or special characters like #$@. <input type="text" style="width: 70%;" [(ngModel)]= "textMessage" (keydown) ="sendTypingEvent()" > However, I want to prevent the event ...

Nested validation schema featuring conditional validation - yes, we've got it covered!

In my Formik object, I have set initial values as follows: {customerDetails: {id: "", name: "", mobileNumber: ""}, notes: {id: "", text: "", type: ""}} How can I create a conditional Yup validati ...

Attempting to revert the imported module back to its initial/default mock configuration

When working on my test file, I utilize a folder named mocks which contains various exported functions. Most of the time, I rely on the mocks folder to perform all necessary tasks. However, there is one scenario where I need to adjust the return value to a ...

NgRx Action Payload fails to trigger Effect, but no error messages are generated

I've exhausted all resources on Stack Overflow and still can't seem to figure this out. The issue lies in passing a payload into the 'GetUser' action. My intention is for this payload to go through the effect, and eventually be sent v ...

Execute a component method once another component has finished loading completely

My setup involves two components that are both being loaded into my <app-root> element as shown below: <app-header [calendarReference]="calendarRef"></app-header> <app-calendar #calendarRef></app-calendar> This is happening ...

Ways to get into the Directive class

@Directive({ selector: '[myHighlight]' }) export class HighlightDirective { static test: number = 5; constructor(private el: ElementRef) { } highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; } } In re ...

Encountering a Node V18 Peer Dependency Conflict错

Can someone please help me understand what's causing this error? Every time I try to install a dependency, this keeps popping up. I'm completely lost and unsure of what's happening. npm ERR! 1 more (the root project) npm ERR! peer ...

The ngModel in Angular 6 did not update the value within the app component

Currently, I am honing my skills in Angular and TypeScript but have encountered a minor issue. Below is the code snippet from my component.html <div> <input [(ngModel)]="mynumber"> N is now {{N}} // some content I want to do with ...

Is it possible to utilize useRef to transfer a reference of an element to a child component?

When I want to mount something into the element with id tgmlviewer, I call it a viewer object. This process works smoothly when there is only one component of this kind. import React, { useEffect } from "react"; import { Viewer } from "../.. ...

Unable to loop through the Array

let Users = [ { name: 'John', id: '1', jp: 'USA' }, { name: 'Jane', id: '2', jp: 'Japan' }, ]; export function DisplayUsers(usersList) { return ( <div> {usersList?.map((user ...

ReactJS Tutorial: Simple Guide to Updating Array State Data

const [rowData, setRowData] = useState([]); const old = {id: 'stud1', name: 'jake', room: '2'}; const newData = {name: 'jake', room: '3A'}; useEffect(() => { let ignore = false; ...

Ways to verify if a value corresponds to a particular data type

Is there a more elegant way for TypeScript to check if a value matches a specific type without actually invoking it, instead of the method described below? Consider the following example: import { OdbEventProcessorFunc } from "./OdbEventProcessor&quo ...

Implement a grid control in Kendo-UI for Angular 2 that includes checkboxes in the first column

What is the process for adding a checkbox to the first column of a Kendo UI Angular2 grid? How can the checked status be retrieved for each row in the data? ...

Combining Two Related API Requests using Angular Observables and RxJS

If I have two API calls that return JSON: First call (rows): { {"row": 1, detailId: "a"} {"row": 2, detailId: "b"} } Second call (rowDetails): { details: { row details } } The task at hand is to fetch rows first, then iterate through each row o ...