Angular 4 HTTP Requests Failing to Retrieve JSON Data

I am currently working with the following method in my Typescript:

allPowerPlants(onlyActive: boolean = false, page: number = 1): PowerPlant[] {
    const params: string = [
      `onlyActive=${onlyActive}`,
      `page=${page}`
    ].join('&');
    const path = `${this.allPowerPlantsURL}?${params}`;
    this.apiService.get(path).map(
      powerplants => {
        powerplants.map(item => {
          if (this.isPowerPlant(item)) {
            // make the item an instance of PowerPlant
            this.powerPlants.push(item as PowerPlant);
          }
      });
    },
    err => {
        console.log('oops **** some error happened');
      // handle error
    });
    console.log('powerplants obtained is *****************+ ');
    console.log(this.powerPlants);
    return this.powerPlants;
  }

The get method in my codebase is structured like this:

import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import { Headers, Http, Response, URLSearchParams } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class ApiService {
  loading: boolean;
  data: Object;
  constructor(
    private http: Http,
  ) {}


    get(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any> {
        console.log('sending request to ' + `${environment.api_url}${path}`);
        return this.http.get(`${environment.api_url}${path}`, { search: params })
          .catch(this.formatErrors)
          .map((res: Response) => {
            console.log('response as json is ' + res.json());
            res.json();
        });
      }
}

This is what my isPowerPlant method looks like:

isPowerPlant(item: any): item is PowerPlant {
    // check for the required properties of PowerPlant here and return true/false.
    // example:
    console.log('in the static method');
    const vvvv = item['maxPower'] && item['minPower'];
    console.log(vvvv);
    return vvvv;
  }

Upon running the above code, I noticed that the response was not being printed in the console log. The server logs also showed no indication of the request being sent.

To rectify this issue, I modified the allPowerPlants method to utilize the subscribe function instead of map:

this.apiService.get(path).subscribe(...)

By making this change, I was able to confirm data retrieval from the server by checking the server logs.

My goal is to have the allPowerPlants method return an array of PowerPlants defined as shown below:

export interface PowerPlant {
  powerPlantId: number;
  powerPlantName: string;
  minPower: number;
  maxPower: number;
  powerPlantType: string;
  rampRateInSeconds?: number;
  rampPowerRate?: number;
}

However, due to the use of Observables, multiple server calls were being made by my Angular app resulting in unnecessary requests as evidenced by the server logs:

[info] application - GET /powerPlants?onlyActive=false&page=1 took 3192ms HTTP status >> 200
[info] application - GET /powerPlants?onlyActive=false&page=1 took 2974ms HTTP status >> 200
...

The response data from the server includes the following information:

[ {
  "powerPlantId" : 1,
  "powerPlantName" : "Organization-001",
  ...
} ]

How can I optimize the allPowerPlants method to make a single server call while handling the Observable result effectively?

In my HTML template, I utilize the data fetched as follows:

<div class="ui grid posts">
  <app-powerplant
    *ngFor="let powerPlant of allPowerPlants()"
    [powerPlant]="powerPlant">
  </app-powerplant>
</div>

Answer №1

Snippet of code retrieving data from the server:

this.apiService.get(path).map(
      powerplants => {
       ...
          }

Wait! No data appears because you forgot to subscribe to it! Make sure to include this section:

this.apiService.get(path).subscribe(
      powerplants => {
        this.powerPlants = powerplants
        // You can remove the mapping and handle it in your service.
    },
    err => {
        console.log('Oops, an error occurred.');
      // Handle any errors here.
    });

Also, update your service with the following:

get(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any> {
        console.log('Sending request to ' + `${environment.api_url}${path}`);
        return this.http.get(`${environment.api_url}${path}`, { search: params })
          .catch(this.formatErrors)
          .map((res: Response) => {
            <PowerPlant[]> res.json();
        });
      }

Please note that the mapping may need adjustment depending on the actual data returned.

I hope this explanation helps you.

Answer №2

Alright, countless examples can be found online explaining how to handle http requests, with plenty available right here...

Typically, you would create a service with a get method avoid using reserved words like GET for your method name... in this case, it could be named getAllPowerplants.

As for the API service in question, it seems to be in good shape (aside from the naming convention).

Next, within the component, you might have code similar to this:

this.apiService.getAllPowerplants.subscribe(data => {
  console.log(data);
});

Remember to subscribe only once (ngOnInit is a suitable location) in order to execute it.

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

Exploring JSON data within PostgreSQL

My task involves extracting spatial data from a json file. The file contains the following information: {"vertices":[{"lat":46.744628268759314,"lon":6.569952920654968}, {"lat":46.74441692818192,"lon":6.570487107359068}, {"lat":46.7442611 ...

NgFor is designed to bind only to Iterables like Arrays

After exploring other questions related to the same error, I realized that my approach for retrieving data is unique. I am trying to fetch data from an API and display it on the page using Angular. The http request will return an array of projects. Below ...

Angular Elements: the crucial link to Material Dependencies

Currently in the process of developing an Angular Element for integration into various projects. This element will serve as a component housing Angular Material components within its template, necessitating the inclusion of a linked Material theme CSS file ...

Facing issues with Observable and HTTP JSON in Angular

I've been struggling with an issue where I'm unable to display the "datos" variable in the *ngFor loop. I suspect the problem lies in the rendering process, so I tried implementing "Observable", but unfortunately, it didn't resolve the issue ...

Is there a way to retrieve the status_code 400 in Angular?

How can I determine if the status code equals 400 in Angular to display a notification? I attempted the following method: signUp() { let body = { login: this.username, nom: this.nom, prenom: this.prenom, adress: thi ...

Integrating Video.js with the latest version of Angular, Angular

Looking to integrate Video.js into my Angular 6 project and retrieve the current play time and video duration. I came across the @types/video.js library but unsure of the correct way to utilize it. Any advice on how to properly implement it? ...

Setting up a Node.js http2 server along with an http server specifically designed for a single

In my upcoming project, I am interested in implementing the http2 protocol. My goal is to have both http and http2 servers running on a single domain and port, if feasible. When a client that does not support http2 connects, communication will default to ...

In Angular, what is the best way to change the format of the timestamp '2019-02-22T12:11:00Z' to 'DD/MM/YYYY HH:MM:SS'?

I am currently working on integrating the Clockify API. I have been able to retrieve all time entries from the API, which include the start and end times of tasks in the format 2019-02-22T12:11:00Z. My goal is to convert the above date format into DD/MM/Y ...

What is the best way to activate multiple variable states (same state) in Angular animations?

I have already checked out the explanation for angular2-height-animation-same-state-transition, but it did not provide the help I needed. I am currently working on creating a carousel similar to the ones you see on eBay or Amazon sites, specifically in th ...

Struggling with defining content and background scripts while using AngularJS2 CLI to build a Chrome extension

After creating a brand new AngularJS-2 application using the cli tool from github, I discovered that running ng build compiles my sources into a /dist folder. As I am developing a chrome extension, I need to specify the location of my content script (whi ...

How can I incorporate the LIKE operator in a query when dealing with PostgreSQL's String array type using TypeORM?

My database backend is PostgreSQL and I have a TypeORM object simplified as follows: @Entity() @Index(['name'], {unique: true}) export class Foo extends BaseEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column() name: st ...

Applause tally problem in Ionic3

For my university project, I am utilizing Ionic-3 and attempting to achieve a similar effect as shown in this example. Please take a look at my code on StackBlitz. I am encountering an issue where I want the count circle to move from the bottom to the top ...

Encountering an error in Angular 13 while trying to retrieve the innerHTML of an element with the ID 'msg'

Seeking assistance to solve this issue. I have exhausted all possible methods to contact the data. (method) Document.getElementById(elementId: string): HTMLElement | null Retrieves a reference to the first object that matches the specified ID attribute v ...

Unexpected JSON response generated by my PHP script following an AJAX request

I'm still learning and I seem to be making a mistake somewhere. I have a PHP result set that I need to iterate through, like this: $rows = array(); while($r = mysql_fetch_assoc($result)) { $rows[] = $r; } echo json_encode ...

Move the angular component to an external location

Is there a way to extract a component from my Angular application 'A' and store it separately in order to easily reload it into another Angular application 'B' with the same node_modules and run it? Essentially, I'm looking to crea ...

Ensuring the Accuracy of String Literal Types using class-validator

Consider the following type definition: export type BranchOperatorRole = 'none' | 'seller' | 'operator' | 'administrator'; Which Class-Validator decorator should I use to ensure that a property matches one of these ...

The efficiency of Ajax JSON timeouts needs improvement

Currently, I'm in the process of developing an interactive map with specific functionalities. Essentially, the user will click on a year (stored as var currentyear) and then select a country (its name stored as var thenameonly). Subsequently, an AJAX ...

Best practices for implementing the map function with TypeScript

I'm currently working on mapping types in a DB using the Map function in JavaScript. This is my first time trying to do this, and I'm eager to learn but I've hit a roadblock. Here is the structure of the DB: const db = { data: [ { ...

What could be causing my "Swiper" component to malfunction in a TypeScript React project?

In my React project, I decided to incorporate the Swiper library. With multiple movie elements that I want to swipe through, I began by importing it as follows: import Swiper from 'react-id-swiper'; Utilizing it in my code like this: <div cla ...

Verify if the term is present in an external JSON file

I am currently using tag-it to allow users to create tags for their posts. At the moment, users can type any word, but I have a list of prohibited words stored in JSON format. I am looking for a way to integrate this list into the tagit plugin so that if ...