Ivaro18 Ivaro18 - 3 months ago 12
TypeScript Question

TypeScript - http.get().subscribe() --> not setting variable

I'm trying to create a

service.ts
file which will handle all of my Http requests in TypeScript (AngularJs2).

Now I do get the right response, but I cannot access the properties outside of the subscribe() function. Let me show you what I mean.

APICaller.service.ts
:



import { Injectable, Inject } from '@angular/core';
import { Http } from '@angular/http';

import { Evenement } from './models/evenement.model';
import { Deelnemer } from './models/deelnemer.model';
import { Comment } from './models/comment.model';

@Injectable()
export class APICaller {
http : Http
baseUrl:string = "http://10.0.4.161:8080";

constructor(@Inject(Http) httpService) {
this.http = httpService;
}

addNewComment(deelnemerId:number, eventId:number, content:string) : Comment{
let results:Comment = {id: 0, content:"", user: "", status: "", date: ""};

this.http.post(this.baseUrl+"/evenementen/"
+eventId +"/deelnemers/"+deelnemerId+"/addComment"
,{
user: 'developer',
content: content
}).subscribe((response) => {
results = response.json();
console.log("results id: "+ results.id);
});

return results;
}
}


component.ts
: (minimized - still needs cleaning)



import { APICaller } from '../../apicaller.service';
import { Comment } from '../../models/comment.model';

@Component({
templateUrl: 'build/pages/deelnemer-details/deelnemer-details.html',
providers: [APICaller]
})

export class DeelnemerDetails {
public deelnemer:any;
public http:Http;
public eventObj;
public newComment;
public comments;
public editComment:any;


constructor(private apiCaller : APICaller, private navCtrl: NavController, navParams : NavParams, public toastCtrl : ToastController, public alertCtrl:AlertController, @Inject(Http) httpService) {
this.eventObj = navParams.get("event");
this.http = httpService;
this.newComment = "";
this.deelnemer={};
this.editComment={
id: -1,
edit: false,
content: ""
}

this.getDeelnemer(navParams.get("deelnemer"));
}

addNewComment(){
let test:Comment = {id: 0, content:"", user: "", status: "", date: ""};

console.log("deelnemer id "+this.deelnemer.id);
console.log("eventObj id "+ this.eventObj.id);
console.log("new comment : "+this.newComment);

test = this.apiCaller.addNewComment(this.deelnemer.id, this.eventObj.id, this.newComment);

console.log("new comment id: "+ test.id);

this.comments.push(
test
);
this.newComment="";

}


Responses and
console.log()



enter image description here

So it seems like within the
.subscribe()
it doesn't set the value of
results
.

Answer

The callback you pass to subscribe(...) is called much later when the response from the server arrives. return results; is called immediately after the call to the server was initiated.

If you change the code to

@Injectable()
export class APICaller {
    http : Http
    baseUrl:string = "http://10.0.4.161:8080";

    constructor(@Inject(Http) httpService) {
        this.http = httpService;
    }

    addNewComment(deelnemerId:number, eventId:number, content:string) : Observable<Comment>{
        let results:Comment = {id: 0, content:"", user: "", status: "", date: ""};

        return this.http.post(this.baseUrl+"/evenementen/"
        +eventId +"/deelnemers/"+deelnemerId+"/addComment"
        ,{
            user: 'developer',
            content: content
        }).map((response) => {
            console.log("results id: "+ results.id);
            return response.json();
        });
    }
}

You can get the result by calling

addNewComment(){
    let test:Comment = {id: 0, content:"", user: "", status: "", date: ""};

    console.log("deelnemer id "+this.deelnemer.id);
    console.log("eventObj id "+ this.eventObj.id);
    console.log("new comment : "+this.newComment);

    this.apiCaller.addNewComment(this.deelnemer.id, this.eventObj.id, this.newComment).subscribe(test => {

      console.log("new comment id: "+ test.id);

      this.comments.push(
         test
      );
      this.newComment="";
    });

   // code here (outside the callback passed to `subscribe(...)`) is again
   // executed before `result` arrives

}

Async execution is contagious and there is no way to return to sync execution once an async execution was initiated.

I changed subscribe() to map() because .map() returns an Observable which can be subscribed to by the caller. .subscribe() returns a Subscription and is worthless in this case to the caller.