"Loop through an array using forEach leads to a subscription that

I am a beginner in Angular and struggling to understand how async functions work. I have written the following code, but I am encountering an error:

GET https://localhost:44353/api/ecams/id/undefined 400
and
["The value 'undefined' is not valid."]
. It seems like the server response is not quick enough to proceed with the next instructions. Can someone guide me on the right approach?

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Exam } from '../_models/exam';
import { IndividualSession } from '../_models/individual-session';
import { IndividualSessionData } from '../_models/individual-session-data';
import { Session } from '../_models/session';
import { User } from '../_models/user';
import { AccountService } from '../_services/account.service';
import { ExamsService } from '../_services/exams.service';
import { IndividualSessionService } from '../_services/individual-session.service';
import { SessionService } from '../_services/session.service';
import { UsersService } from '../_services/users.service';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
  currentUser$: Observable<User>;
  user: User;
  userId: number;
  individualSessionsData: IndividualSessionData[] = [];
  
  tempIndividualSessionData: IndividualSessionData = {} as IndividualSessionData;

  constructor(private accountService: AccountService,
    private individualSessionService: IndividualSessionService,
    private userService: UsersService,
    private examService: ExamsService,
    private sessionService: SessionService) {
       this.tempIndividualSessionData.exam = {} as Exam;
       this.tempIndividualSessionData.individualSession = new IndividualSession();
       this.tempIndividualSessionData.session = {} as Session;
       this.getCurrentUserData();
      }

  ngOnInit(): void {

  }

  onRowClick(){
    
  }

  logout() {
    this.accountService.logout();
  }

  private getCurrentUserData() {
    this.currentUser$ = this.accountService.currentUser$;
    this.currentUser$.subscribe(user => {
      if (!!user) {
        this.user = user;
        this.loadUser(this.user.email);
      }
    });
  }

  loadUser(email: string) {
    this.userService.getUser(email).subscribe(user => {
      if(!!user) {
        this.user = user;
        this.loadId(this.user.email);
      }
    })
  }

  loadId(email: string) {
    this.userService.getId(email).subscribe(id => {
      if(!!id) {
        this.userId = id;
        this.loadIndividualSessions(this.userId);
      }
    })
  }

  loadIndividualSessions(id: number) {
    this.individualSessionService.getIndividualSessions(id).subscribe(sessions => {
      if(!!sessions) {
        sessions.forEach(session => {
          this.tempIndividualSessionData.individualSession = session;
          this.loadSession(session.sessionId);
        });
      }
    })
  }

  loadSession(id: number) {
    this.sessionService.getSession(id).subscribe(session => {
      if(!!session) {
        this.tempIndividualSessionData.session = session;
        this.loadExam(session.examId);
      }
    })
  }

  loadExam(id: number) {
    this.examService.getExamById(id).subscribe(exam => {
      if(!!exam) {
        this.tempIndividualSessionData.exam = exam;
        this.individualSessionsData.push(this.tempIndividualSessionData);
      }
    })
  }
}

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { Exam } from '../_models/exam';
import { Question } from '../_models/question';

@Injectable({
  providedIn: 'root'
})
export class ExamsService {
  baseUrl = environment.apiUrl;
  currentExam: Exam;
  answeredQuestions: Question[];
  correctAnswers: number[];
  currentMark: number;

  constructor(private http: HttpClient) { }

  getExams() {
    return this.http.get<Exam[]>(this.baseUrl + 'exams');
  }

  getExam(title: string){
    return this.http.get<Exam>(this.baseUrl + 'exams/title/' + title); 
  }

   getExamById(id: number){
     return this.http.get<Exam>(this.baseUrl + 'exams/id/' + id); 
   }

}

If anyone can provide assistance, it would be greatly appreciated. Happy coding!

Answer №1

When you encounter the HTTP code 400 error, it indicates that your request is incorrect:

https://localhost:44353/api/ecams/id/undefined

Here are three key points to note:

  1. A simple typo: It should say "exams" instead of "ecams"
  2. The presence of "undefined" suggests that the value you are trying to append is indeed undefined.
  3. If you do not have control over the API and it follows REST principles, the URL should probably read as follows:
    https://localhost:44353/api/exams/1/something
  4. It's advisable to review your method parameters for any instances where they may be undefined or null.

It appears that at least once, session.examId in loadExam() is undefined. Consider updating your code as shown below:


loadExam(id: number) {
    if (id){
        this.examService.getExamById(id).subscribe(exam => {
          if(exam) {
            this.tempIndividualSessionData.exam = exam;
            this.individualSessionsData.push(this.tempIndividualSessionData);
          }
        });
    } else {
        console.error("Exam id is null or undefined.");
    }
}

You can insert a line such as console.log(session); within the sessions.forEach() call to identify any sessions lacking an examId. Additionally, utilize the browser's developer tools to monitor network activity during API requests. Are the requests successful? If yes, make sure you are capturing the results correctly. If not, revisit the parameters you are attempting to send.

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

The @Prop property decorator in Vue cannot be utilized as it is not compatible

I have a Vue 2 component with TypeScript: import Vue from 'vue'; import Component from 'vue-class-component'; import Prop from 'vue-property-decorator'; @Component({ template: require('./template.html'), }) expo ...

Leveraging the Nest JS Validation Pipe in combination with the class-transformer to retrieve kebab-case query parameters

Can someone help me with using the Nest JS Validation Pipe to automatically transform and validate my GET Request Query Params? For example: {{url}}/path?param-one=value&param-two=value In my app.module.ts, I have included the following code to impl ...

The installation failed due to an unresolved dependency when running npm install

Upon performing a git clone, I encountered this error with my project after running npm install: npm ERR! code ERESOLVE npm ERR! npm ERR! While resolving: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6e0f1e1e43081c01001a0b000 ...

What is the method to have VIM recognize backticks as quotes?

Currently working in TypeScript, I am hoping to utilize commands such as ciq for modifying the inner content of a template literal. However, it appears that the q component of the command only recognizes single and double quotation marks as acceptable ch ...

When utilizing the Turf.nearPoint() function, it is important to consider the type of point being used. The documentation for Turf.nearestPoint() appears to be inaccurate

I have some code that needs to be transcribed from another system, so unfortunately I can't easily share it here. If I could, I would just post the entire project. Recently, I attempted to integrate into our project but encountered error messages. T ...

Troubleshooting ngFor Issue in Angular 4

I've double-checked all the required modules and scanned for errors, but unfortunately, nothing seems to be helping me at the moment. As a newcomer to Angular, I'm still in the learning phase. Now, let's take a look at my app.module.ts file ...

Encountering a Difficulty while attempting to Distinguish in Angular

I am currently working on a form where I need to dynamically add controls using reactiveForms. One specific task involves populating a dropdown menu. To achieve this, I am utilizing formArray as the fields are dynamic. Data: { "ruleName": "", "ruleD ...

What is the method for determining the width of a Mat-Table once it has been displayed?

When utilizing Angular Material Mat-Table in conjunction with Angular 8, I am passing the dataSource dynamically. The number of rows and columns varies each time. Is there a method to calculate the width of the table once it is rendered on the screen? &l ...

Guide for creating a function that accepts an array containing multiple arrays as input

I am working with a function called drawSnake and it is being invoked in the following manner: drawSnake( [ [0, 0], [0, 1], [0, 2], [0, 3], [0, 4], ] ); How should I format the input for this function? I have attempted using Array<Array<[numb ...

Ways to Resolve the "TS2533: Object May Be Either 'Null' or 'Undefined'" Error on a Dynamic Object

I'm encountering an issue with the following code snippet: interface Schema$CommonEventObject { formInputs?: { [key: string]: Schema$Inputs; } | null; } interface Schema$Inputs { stringInputs?: Schema$StringInp ...

Enhancing Code Completion Feature for Multiline Strings in Visual Studio Code

When attempting to include HTML code in a multiline string using backticks within TypeScript, I've noticed that VS Code doesn't offer auto-completion for the HTML tags. Take this example: @Component({ selector: 'app-property-binding&ap ...

The method Office.context.mailbox.item.internetHeaders.setAsync has not been configured

I am integrating the Microsoft Office API into Outlook. I'm attempting to add an extra x-header to my email in the composer scope for later identification. To achieve this, I referred to the following documentation: https://learn.microsoft.com/en-us/j ...

What is the best way to create an instance method in a subclass that can also call a different instance method?

In our programming project, we have a hierarchy of classes where some classes inherit from a base class. Our goal is to create an instance method that is strongly-typed in such a way that it only accepts the name of another instance method as input. We d ...

Bringing in a TypeScript module to an Angular component

Having trouble with including a specific library in my component Here is the code for my component which uses geolib as the library: import { Component, OnInit } from '@angular/core'; import { StationsService } from '../../../services/stati ...

One creative method for iterating through an array of objects and making modifications

Is there a more efficient way to achieve the same outcome? Brief Description: routes = [ { name: 'vehicle', activated: true}, { name: 'userassignment', activated: true}, { name: 'relations', activated: true}, { name: &apos ...

Encountered an issue while using OpenAPI 3.1 with openapi-generator-cli typescript-fetch. Error: JsonParseException - The token 'openapi' was not recognized, expected JSON String

I am interested in creating a TypeScript-fetch client using openapi-generator-cli. The specifications were produced by Stoplight following the OpenAPI 3.1 format. However, when I execute the command openapi-generator-cli generate -i resources/openapi/Attri ...

Failed deployment of a Node.js and Express app with TypeScript on Vercel due to errors

I'm having trouble deploying a Nodejs, Express.js with Typescript app on Vercel. Every time I try, I get an error message saying "404: NOT_FOUND". My index.ts file is located inside my src folder. Can anyone guide me on the correct way to deploy this? ...

Alter the class based on the incoming string from the rxjs stream

I have a stream that outputs strings, and based on these strings I want to apply certain classes to a specific tag: If the string is "ok", add class "fa-check" If the string is "loading", add classes "fa-spin" and "fa-spinner" If the string is "error", a ...

Troubleshooting Connectivity Problems with Angular Single Page Application (SPA) and .NET Core 3.0

I have successfully created an API with a swagger interface running on localhost:5599. When I do a GET request to localhost:5599/api/owner, I receive a JSON object of owners without any issues. Now, my next task is to create an Angular interface for this ...

How can you make sure that a class property in TypeScript always matches the name of the class?

Click here for an example interface ICommandHandler<T> { type: string // how can we ensure that this equals T.name? handle(command: T): void; } interface ICommand {} class CreateTaskCommand implements ICommand{} class CreateTaskCommandHandler ...