0

I've been rewriting an Angular app which previously omitted the use of http requests. For this reason, lots of logic is contained in a service component and the http request was simulated by working with an array of the following format:

[{"name": "somename1", "subset1": [
  {"name": "somesubname1", "subset2": [
    {"somemetric1": 0, "somemetric2: 1, "somemetric3": 2}]}]}]

This is exactly the format which is also displayed on some web api (https://localhost:5001/api/values e.g.).

My service looks like this:

import { Injectable } from '@angular/core'
import { Subject, Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';


@Injectable()

export class StrategyService{

    data:any

    constructor(private httpClient: HttpClient) {
    }

    getData() {
        this.data = this.httpClient.get("https://localhost:5001/api/values")
    }

If I console.log(this.data) in e.g. getData() and call this function when running my app, "undefined" is returned in the console. When I would replace the body of getData() with

this.httpClient.get("https://localhost:5001/api/values").subscribe(data => {data = console.log(data)})

the console does return the array in the format as desired (and displayed in the first block). Console logging is in fact not what I need since I need to be able to access the data in other functions inside my service component which would need array-specific methods such as .find etc.

I feel like this is a simple thing to do, but I've had no succes so far. I've tried

import { Injectable } from '@angular/core'
import { Subject, Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';


@Injectable()

export class StrategyService{

    dat:any

    constructor(private httpClient: HttpClient) {
    }

    getData() {
        this.httpClient.get("https://localhost:5001/api/values").subscribe(data => {this.dat = data})
    }

console.log(this.dat) still returns "undefined".

Kasper Cools
  • 125
  • 5
  • 1
    this.data is undefined. but this.dat is not (check your naming 'data' <-> 'dat') – Wouter Vandenputte Jul 31 '19 at 18:18
  • What do you want to do with the data more exactly? The power of observables (that you get back from `httpClient.get`) is that you can chain the response for instance with other observables, and display the result in your template using an async pipe, such as `
    {{ item.name }}
    `
    – Patrick Jul 31 '19 at 18:47
  • I'm looking to manipulate the data and do operations with it inside my service. I've implemented a ton of stuff using array methods so in the end I'm just looking to make a copy of the observable and store/use it as an array. I'm aware this is probably not the best way to go about it, but in the end this is what I need. – Kasper Cools Aug 01 '19 at 07:21

1 Answers1

2

This is a classic starting problem everyone has with async code. Have a research of rxjs + how async code works in Typescript.

The solution to your problem is to check the data within the subscribe block as that happens after the response from your api is back.

this.httpClient.get("https://localhost:5001/api/values").subscribe(data => console.log(data))
public myFunction() {
this.httpClient.get("https://localhost:5001/api/values").subscribe(data => {
   this.data = data;
   console.log(this.data); // data is defined here
})
console.log(this.data); // data will be undefined here
}

Links to useful resources:
https://www.learnrxjs.io/
https://angular.io/guide/http

James
  • 2,516
  • 2
  • 19
  • 31
  • I'm looking to manipulate the data and do operations with it inside my service. I've implemented a ton of stuff using array methods so in the end I'm just looking to make a copy of the observable and store/use it as an array. I'm aware this is probably not the best way to go about it, but in the end this is what I need. – Kasper Cools Aug 01 '19 at 07:21
  • 1
    So you can't just copy the observable because the point is, is that it's a stream of data and you have no idea when it will be returned. The only time you can be certain is within the subscription. You'll have to do your manipulation in functions called by the subscribe. So in my example where you see the `this.data = data` you could call your array transformation functions. (You should know that within the subscribe, when you reference `data` it is no longer an observable and is a regular array). If you don't understand this, it would really help you if you looked at the links above :) – James Aug 01 '19 at 08:24