0

So I have a variable called stuff, which is declared as stuff:any and I would like to populate it with the data that I get from:

this.http.post("WORKING_IP_ADDRESS", JSON.stringify(
      {"thing1": this.thing1,
      "thing2": this.thing2,
    }), {headers: headers}).map(
      res => res.json()).subscribe(
        data => {
          (JSON.stringify(data));
        })

When I run an alert() method on the last JSON.stringify(data));, I get the data that I want, but when I try to set it equal to the stuff variable by doing this.stuff = JSON.stringify(data));, it doesn't work. I'm new to Angular, so I know I'm probably doing something wrong. Anyone know what I need to do to get the final JSON.stringify(data) into my stuff variable?

Evan Bloemer
  • 1,051
  • 2
  • 11
  • 31

1 Answers1

2

The reason is that http.post is a observable. That means that its gonna resolve later. It's gonna resolve later because its gonna take some time to connect to that working ip address, get the data and do something with it.

Imagine a scenario like this

let stuff = 'no';

// Equal to http.post
const resolvesLater = setTimeout(function() {
    stuff = 'yes';
    console.log(stuff);
},2000);

console.log(stuff);

https://jsfiddle.net/7c6kfurp/ Open up the console and press play. See what happens.

You would think that the console would look like yes yes

But it actually is gonna be no yes

Because what happens in the setTimeout happens later. So the order of the lines don't tell you in what order the code executes.

  • Its gonna set stuff = 'no' at the beginning.
  • Then its gonna go into the setTimeout/http.post function
  • That's gonna take some time.
  • Meanwhile the browser continues
  • It logs out stuff (still no)
  • Then the setTimeout/http.post resolves
  • Its gonna set stuff = yes
  • Then log out stuff (which is now yes)

In angular 2 you subscribe to observables (like you do) but it would probably be better to decouple the fetch and subscribe. So create a service with a function:

fetchStuff(): Observable<Stuff[]> {
        return his.http.post("WORKING_IP_ADDRESS", JSON.stringify({
            "thing1": this.thing1,
           "thing2": this.thing2,
       }), {headers: headers}).map(res => res.json());
    }

And then you subscribe to it and assign the stuff variable for the views

getStuff() {
    this.MyService.fetchStuff()
        .subscribe(stuff => this.stuff= stuff);
}

And finally in your view

<ul class="items">
    <li *ngFor="let item of stuff>
        <span>{{item.property}}</span>
    </li>
</ul>

Observables means that when the object changes all other objects that are dependant on it are notified.

So you make a request to your working-ip, first nothing happens, like I explained above. We're waiting for the server to respond, so something with the data you sent and then send you something back.

In order to know when something happened, you subscribe to it. Just like you would subscribe a newspaper to get the latest news. When something happens you get notified. You want to know when you get response from the-working-ip.

The reason I broke it up was to seperate the fetching and the subscription, just to seperate the concerns. You don't have to and I've probably confused things more for you. Sorry about.

Simply try this:

this.http.post("WORKING_IP_ADDRESS", {
    "thing1": this.thing1,
    "thing2": this.thing2
}, {headers: headers})
.map(res => res.json())
.subscribe(data => this.stuff = data);

Here's a link on how to create services https://angular.io/docs/ts/latest/guide/server-communication.html

Bergur
  • 3,962
  • 12
  • 20
  • That helps, but how do I then capture what http.post returns? – Evan Bloemer May 10 '17 at 00:23
  • updated with some example, but after some googling this guy explains it better: http://stackoverflow.com/questions/34671715/angular2-http-get-map-subscribe-and-observable-pattern-basic-understan – Bergur May 10 '17 at 00:52
  • I'm sorry, I'm a little confused on the service and subscribe stuff. I don't exactly know how to create services or where you are getting fetchData() from when it isn't mentioned anywhere else. – Evan Bloemer May 10 '17 at 01:07
  • Yeah fetchData is a typo, sorry it all becomes data data and stuff ;) I've updated my answer though. Hopefully this helps. – Bergur May 10 '17 at 01:43
  • So I figured out how to get services running, and my event happens when I click a button, however, when I click it the first time, I get `undefined`, but when I click it a second time I get the `stuff` I was hoping for. Any idea what's going wrong now? – Evan Bloemer May 10 '17 at 02:08
  • I decided to make a new question out of it here: http://stackoverflow.com/questions/43882643/ionic-2-http-provider-returning-undefined-the-first-time-but-the-correct-data-t Thank you for all your help! – Evan Bloemer May 10 '17 at 02:27
  • Glad to send you in the rigth direction :) – Bergur May 10 '17 at 02:35