rardav
rardav

Reputation: 43

subscribe inside foreach returning undefined

Sorry for I am still a beginner in Angular and I do not understand how async is working. I wrote the following code, but I do get an error: GET https://localhost:44353/api/ecams/id/undefined 400 and ["The value 'undefined' is not valid."]. My guess is that the answer from server does not come quick enough so that it can start the next instruction. How should I proceed?

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); 
   }

}

Thank you in advance and happy coding!

Upvotes: 0

Views: 187

Answers (1)

julianpoemp
julianpoemp

Reputation: 2042

The HTTP code 400 error shows that your request is wrong:

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

There are three points I see clearly:

  1. There is a typo: It should be "exams" instead of "ecams"
  2. The "undefined" shows that the value you try to append is undefined.
  3. If you are not the developer of the API and it's a REST API I assume that the URL should be rather: https://localhost:44353/api/exams/1/something
  4. It's recommended to check the parameters of your method if they are undefined or null.

I assume, that session.examId in loadExam() is undefined at least one time. Try to change your code to:


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 add an console.log(session); line in the sessions.forEach() call and check if there are any sessions without examId. Further more you can open the dev tools in your browser and check the network traffic while doing requests to the API. Do the requests work? If yes, there is an error in catching the results. If no, there are errors in your requests. Check the parameters you are trying to send again.

Upvotes: 1

Related Questions