1

I have a webapp that gets via Json stuff put it in objects to display them. I already did it two times with services and classes. But now i copy and paste the old code make some slight changes to make sure it redirect to the good classes but now i get an array with functions instead an array with objects.

Here you see the array open in console

And here the are closed

Here is my constructor that calls upon the the service classes and send things to the console

constructor(private featureService : FeatureService, private scenarioservice : ScenarioService, private failuresService : FailuresService){
    //hier worden de features en failures opgehaald
    this.featureService.getFeatures().subscribe(res => {
      this.featureArray = res.getFeatureArray();
      console.log(res.getFeatureArray());
    });
      this.failuresService.getFailures().subscribe(res => {
      this.failureArray = res.getFailureArray();
      console.log(res.failures[0].method);
      console.log(this.failureArray);
    });

  }

}

Here is failuresService.getFailures:

import { Injectable } from "@angular/core";
import {Http, Response} from "@angular/http";
import {Failure} from "./Failure";
import {Failures} from "./failures";


@Injectable()
export class FailuresService {
  constructor(protected http: Http) {}


  getFailures() {
    return this.http.get('http://localhost:8080/testresultaten')
      .map((response: Response) => response.json())
      .map(({failures = [Failure]}) => new Failures(failures));// deze error is bullshit
  }
}

This is the Json that I get and want to get in an class:

{
  "failures:": [
    {
      "method": "canRollOneGame",
      "object": "BowlingGame.GameTest"
    },
    {
      "method": "canCountNighteeneight",
      "object": "FizzBuzz.FizzBuzzTest"
    }
  ]
}

Here are the Failure and Failures classes:

import {Failure} from "./Failure";
export class Failures {

  constructor(public failures : Failure[]){}
  public getFailureArray(): Failure[]{
    return this.failures;
  }

}


export class Failure{

  constructor(public method : String , public object : String ){  }
}
Nick Alexander
  • 361
  • 2
  • 5
  • 21
  • That failure service looks wonky, in particular, the failures mapping. The arg you are passing to new Failures is { failures = [Failure] }: what is that supposed to do? If it's a typed array wouldn't is just be failures: Array (or for testing, just omit the type and pass failures, and see if it works)? Also, are you sure the import for Failure is right (or is it just named uppercase, as oppose to the usual lower case, this may not be broken it just looks strange). – Tim Consolazio Jan 10 '17 at 11:33
  • I have failures = [Failure] because i get from JSON an array of Failure. the code is the same as the working FeatureService expect from the class names ofcourse – Nick Alexander Jan 10 '17 at 11:42
  • Right, what I mean is, what exactly does { failures = [Failure] } do? You appear to be setting a variable (failures) equal to an array that contains a function ([Failure]), and then feeding that variable to your Failures constructor. So you are mapping "new Failures ( [ Failure ] )". This would return an array of "Failure" functions, which is what I think your problem is. If failures should be an array of Failures, wouldn't the syntax be failures: Array? TS may call things "Types", but remember that's just sugar. "Types" are still just JS functions under the hood. – Tim Consolazio Jan 10 '17 at 12:03
  • This is the Failures constructor : { constructor(public failures : Failure[]){}} so I need an array to make the object. so I want an array of Failure object – Nick Alexander Jan 10 '17 at 12:06
  • I get that. But what you are feeding that constructor isn't a failures array. It is an array with a single function in it, every time ([Failure]). I could be wrong, but I have never see that { failures = [Failures] } syntax. Try removing that, and it it's place, just put "failures", and see what happens. Don't worry about the type for now, just take the incoming arg (failures) and feed THAT, as-is, to your constructor. – Tim Consolazio Jan 10 '17 at 12:08
  • I tried it (the failures in stead of failures = [Failure] ) and console.log(res); gives : {Failures {failures: undefined}}. So it looks like it is now completely undefined – Nick Alexander Jan 10 '17 at 12:16
  • Did you remove the brackets? Look at my code in the answer. BTW if that's just showing "undefined", then something else is wrong with your code, but we'll get to that. – Tim Consolazio Jan 10 '17 at 12:18

3 Answers3

0

I could be wrong but this doesn't look right:

getFailures() {
    return this.http.get('http://localhost:8080/testresultaten')
      .map((response: Response) => response.json())
      .map(({failures = [Failure]}) => new Failures(failures));// deze error is bullshit
  }

That last mapping, I'm not sure what it is supposed to do. I've never seen that syntax (doesn't mean it's wrong). I get that you have an incoming array. But what this syntax does {failures = [Failure]} is what I think your problem is. I don't think that will do what you think.

Try this and see what happens:

.map(failures => { console.log ( failures ); new Failures(failures) } );// deze error is bullshit

If you try that with your old mapping, and then this new one, it'd be interesting to see what that console.log traces out. I think doing it your way, you won't see what you expect.

If that sorts you out, then you can try typing the incoming payload (though I'm not sure it'll work; it should be receiving JSON from the previous mapping).

.map( (failures: Array<Failure>) => { console.log ( failures ); new Failures(failures) } );
Tim Consolazio
  • 4,802
  • 2
  • 19
  • 28
  • I now get Object{ failures: : Array[2] 0 : Object 1 : Object } but getfailureArray () is undefined but I can tinker with this maybe I will find something, thanks for explaining so thorough for me – Nick Alexander Jan 10 '17 at 12:18
  • Yeah that second mapping is your big problem. You are doing this: svcResult => toJson => to Failures Array. So you are feeding in the result, turning it into json, then submitting that JSON to the failures mapping. Just keep it vanilla and simple to get it rolling (the way JS is meant to be) and then roll in your Types. – Tim Consolazio Jan 10 '17 at 12:23
  • Why do you have an ; after { console.log ( failures ); because now the return is al turend around – Nick Alexander Jan 10 '17 at 12:24
  • The ; separates the statement in the map function. I think you're not really sure what you're getting back from your service here. Your return is just an object with a property "failures" with an array of objects on it. There is no "getFailureArray" function. You just access the "failures" property of the return. – Tim Consolazio Jan 10 '17 at 12:27
  • Now I get back an observable and a long time ago I made that strange .map so that it is an object because I need an object so that in a other part of the program I can call upon the individual part of the classes like name or something like that – Nick Alexander Jan 10 '17 at 12:49
  • Doesn't work that way though, at least not as you have it coded here. I'd just keep it simple. – Tim Consolazio Jan 10 '17 at 12:50
  • But that is why I made that strange .map do you know an way to use it my way with an other map? – Nick Alexander Jan 10 '17 at 12:52
0

So if I read it correctly: Your goal is to create an array of Failure objects with the values coming from a JSON array where each of this has a method you'd like to execute somewhere in the code.

If thats the case then I understand what went wrong. As Tim Consolazion mentioned in the comments you only get the values for the Failure object not the Failure object itself (See custom created method error: "is not a function"). So in order to execute the commands from Failure you have to create for each object in your JSON array a Failure object. Something like this:

return this.http.get('http://localhost:8080/testresultaten')
  .map((response: Response) => {
      let content = response.json();
      let failureList: Failure[] = [];

      content.forEach(failure => {
                failureList.push(new Failure(failure.method, failure.object))
            });

      return failureList || {};
  }

What I wonder is where you found {failures = [Failure]}? I've never seen this before and I've no idea what this is for.

EDIT: I edited the question so it fits your class Failure. The failure in content.forEach(failure => { in an object from your JSON array. You can access the values of it like it is a normal object. In your case with failure.method and failure.object.

Community
  • 1
  • 1
SuffPanda
  • 348
  • 2
  • 17
  • I now also wonder where I found that I found it (or made) around 5 weeks ago for something that is almost the same as this and to this day that still works. I am now gonna try youre fix – Nick Alexander Jan 10 '17 at 13:08
  • He does not know failure and foo, bar – Nick Alexander Jan 10 '17 at 13:14
  • has `Failure` a constructor? If not then create one and give all the values in your object in the JSON array as parameter. Example: you have an array with two objects with the value foo and bar. In order to create an object out of it you need a constructor that takes the value foo and bar as a parameter. – SuffPanda Jan 10 '17 at 13:28
  • The constructor is { constructor(public method : String , public object : String ){ } } – Nick Alexander Jan 10 '17 at 13:37
  • @Nick can you edit your post with your JSON and `Failure` class? – SuffPanda Jan 10 '17 at 13:42
  • I now get an Observable back but I want/need an object so that i can use the individual pieces of information – Nick Alexander Jan 10 '17 at 14:19
  • You're close to your finish line. What you now return is an `Observable`. With `.subscribe()` you now define what it should do with `Failure[]` in the `Observable`. Ergo: `.subscribe(observable => this.failureArray = observable)`. – SuffPanda Jan 10 '17 at 14:37
0

I found my problem in the Json the name was function: but in my code it was function so all that was necessary was to make sure it sends function instead of function:

Nick Alexander
  • 361
  • 2
  • 5
  • 21