Get result from HttpGet Request in “getter” method Angular 7 service











up vote
0
down vote

favorite












This is probably pretty simple, but Angular isn't exactly my forte and it's taking me a bit more time than I anticipated. I have a service that calls an external API, and I want to get the variable on app initialisation and to use it in multiple other components.



I have the following service:



import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
providedIn: 'root'
})
export class DatabaseConnectionService {

API_URL: string = "http://localhost:4044";

apiResult;

constructor(private http: HttpClient) {
this.dbConn.getApiRoot()
.subscribe(
data => this.apiResult = { message: data['message'] }
);
}

getApiRoot() {
return this.http.get<Apiroot>(this.API_URL);
}

returnApiResult() {
return this.apiResult;
}

}


In any of the other components, I need to be able to call the returnApiResult() and get the value of the variable, but it returns as empty since it's an observable (which I think should have already be assigned, since it's in the constructor for the service). Any help is appreciated.










share|improve this question
























  • Its not necessary that you will get the response data since you initiated the call in constructor.
    – Sunil Singh
    Nov 9 at 15:16










  • Even though it's in the constructor, it's asynchronous, so there is no guarantee is has finished loading when you call returnApiResult. Instead, you should return the actual Observable, and call subscribe in the components that need it
    – user184994
    Nov 9 at 15:17












  • @user184994 Yeah, it works that way, I was kind of hoping to initialise all the data on application load, and just access it through the components. This way it would minimise the API requests too.
    – Neekoy
    Nov 9 at 15:19










  • What version of rxjs are you using?
    – user184994
    Nov 9 at 15:28















up vote
0
down vote

favorite












This is probably pretty simple, but Angular isn't exactly my forte and it's taking me a bit more time than I anticipated. I have a service that calls an external API, and I want to get the variable on app initialisation and to use it in multiple other components.



I have the following service:



import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
providedIn: 'root'
})
export class DatabaseConnectionService {

API_URL: string = "http://localhost:4044";

apiResult;

constructor(private http: HttpClient) {
this.dbConn.getApiRoot()
.subscribe(
data => this.apiResult = { message: data['message'] }
);
}

getApiRoot() {
return this.http.get<Apiroot>(this.API_URL);
}

returnApiResult() {
return this.apiResult;
}

}


In any of the other components, I need to be able to call the returnApiResult() and get the value of the variable, but it returns as empty since it's an observable (which I think should have already be assigned, since it's in the constructor for the service). Any help is appreciated.










share|improve this question
























  • Its not necessary that you will get the response data since you initiated the call in constructor.
    – Sunil Singh
    Nov 9 at 15:16










  • Even though it's in the constructor, it's asynchronous, so there is no guarantee is has finished loading when you call returnApiResult. Instead, you should return the actual Observable, and call subscribe in the components that need it
    – user184994
    Nov 9 at 15:17












  • @user184994 Yeah, it works that way, I was kind of hoping to initialise all the data on application load, and just access it through the components. This way it would minimise the API requests too.
    – Neekoy
    Nov 9 at 15:19










  • What version of rxjs are you using?
    – user184994
    Nov 9 at 15:28













up vote
0
down vote

favorite









up vote
0
down vote

favorite











This is probably pretty simple, but Angular isn't exactly my forte and it's taking me a bit more time than I anticipated. I have a service that calls an external API, and I want to get the variable on app initialisation and to use it in multiple other components.



I have the following service:



import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
providedIn: 'root'
})
export class DatabaseConnectionService {

API_URL: string = "http://localhost:4044";

apiResult;

constructor(private http: HttpClient) {
this.dbConn.getApiRoot()
.subscribe(
data => this.apiResult = { message: data['message'] }
);
}

getApiRoot() {
return this.http.get<Apiroot>(this.API_URL);
}

returnApiResult() {
return this.apiResult;
}

}


In any of the other components, I need to be able to call the returnApiResult() and get the value of the variable, but it returns as empty since it's an observable (which I think should have already be assigned, since it's in the constructor for the service). Any help is appreciated.










share|improve this question















This is probably pretty simple, but Angular isn't exactly my forte and it's taking me a bit more time than I anticipated. I have a service that calls an external API, and I want to get the variable on app initialisation and to use it in multiple other components.



I have the following service:



import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
providedIn: 'root'
})
export class DatabaseConnectionService {

API_URL: string = "http://localhost:4044";

apiResult;

constructor(private http: HttpClient) {
this.dbConn.getApiRoot()
.subscribe(
data => this.apiResult = { message: data['message'] }
);
}

getApiRoot() {
return this.http.get<Apiroot>(this.API_URL);
}

returnApiResult() {
return this.apiResult;
}

}


In any of the other components, I need to be able to call the returnApiResult() and get the value of the variable, but it returns as empty since it's an observable (which I think should have already be assigned, since it's in the constructor for the service). Any help is appreciated.







angular angular7






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 at 12:31









Goncalo Peres

9571311




9571311










asked Nov 9 at 15:14









Neekoy

798921




798921












  • Its not necessary that you will get the response data since you initiated the call in constructor.
    – Sunil Singh
    Nov 9 at 15:16










  • Even though it's in the constructor, it's asynchronous, so there is no guarantee is has finished loading when you call returnApiResult. Instead, you should return the actual Observable, and call subscribe in the components that need it
    – user184994
    Nov 9 at 15:17












  • @user184994 Yeah, it works that way, I was kind of hoping to initialise all the data on application load, and just access it through the components. This way it would minimise the API requests too.
    – Neekoy
    Nov 9 at 15:19










  • What version of rxjs are you using?
    – user184994
    Nov 9 at 15:28


















  • Its not necessary that you will get the response data since you initiated the call in constructor.
    – Sunil Singh
    Nov 9 at 15:16










  • Even though it's in the constructor, it's asynchronous, so there is no guarantee is has finished loading when you call returnApiResult. Instead, you should return the actual Observable, and call subscribe in the components that need it
    – user184994
    Nov 9 at 15:17












  • @user184994 Yeah, it works that way, I was kind of hoping to initialise all the data on application load, and just access it through the components. This way it would minimise the API requests too.
    – Neekoy
    Nov 9 at 15:19










  • What version of rxjs are you using?
    – user184994
    Nov 9 at 15:28
















Its not necessary that you will get the response data since you initiated the call in constructor.
– Sunil Singh
Nov 9 at 15:16




Its not necessary that you will get the response data since you initiated the call in constructor.
– Sunil Singh
Nov 9 at 15:16












Even though it's in the constructor, it's asynchronous, so there is no guarantee is has finished loading when you call returnApiResult. Instead, you should return the actual Observable, and call subscribe in the components that need it
– user184994
Nov 9 at 15:17






Even though it's in the constructor, it's asynchronous, so there is no guarantee is has finished loading when you call returnApiResult. Instead, you should return the actual Observable, and call subscribe in the components that need it
– user184994
Nov 9 at 15:17














@user184994 Yeah, it works that way, I was kind of hoping to initialise all the data on application load, and just access it through the components. This way it would minimise the API requests too.
– Neekoy
Nov 9 at 15:19




@user184994 Yeah, it works that way, I was kind of hoping to initialise all the data on application load, and just access it through the components. This way it would minimise the API requests too.
– Neekoy
Nov 9 at 15:19












What version of rxjs are you using?
– user184994
Nov 9 at 15:28




What version of rxjs are you using?
– user184994
Nov 9 at 15:28












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










In your constructor, change the code like so:



  import { shareReplay } from 'rxjs/operators';

//...

constructor(private http: HttpClient) {
this.apiResult = this.dbConn.getApiRot().pipe(shareReplay());
}


By using the shareReplay operator, it will share the results among multiple subscribers, and replay the results. This way, your components can still subscribe:



  this.service.apiResult.subscribe(() => console.log("Done"))


But the data will only need to be loaded by the service once, on application load






share|improve this answer























  • Perfect - it does the trick and leaves only 1 line of logic in the other components which is what I was going for. I think it's worth mentioning that last() is contained in "import { last } from 'rxjs/operators';", other than that this is the correct answer. Thanks :)
    – Neekoy
    Nov 9 at 15:44










  • @Neekoy Very good point, I'll add it in now. Glad to help
    – user184994
    Nov 9 at 15:44










  • Not sure this will only load the data once if more than one component subscribes to it.
    – Aviad P.
    Nov 9 at 16:29










  • @AviadP Having just played around with this, you're completely right, my mistake. @Neekoy I have made a change to use shareReplay instead of last, which should be more efficient. Please use that instead
    – user184994
    Nov 9 at 18:15











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53228403%2fget-result-from-httpget-request-in-getter-method-angular-7-service%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










In your constructor, change the code like so:



  import { shareReplay } from 'rxjs/operators';

//...

constructor(private http: HttpClient) {
this.apiResult = this.dbConn.getApiRot().pipe(shareReplay());
}


By using the shareReplay operator, it will share the results among multiple subscribers, and replay the results. This way, your components can still subscribe:



  this.service.apiResult.subscribe(() => console.log("Done"))


But the data will only need to be loaded by the service once, on application load






share|improve this answer























  • Perfect - it does the trick and leaves only 1 line of logic in the other components which is what I was going for. I think it's worth mentioning that last() is contained in "import { last } from 'rxjs/operators';", other than that this is the correct answer. Thanks :)
    – Neekoy
    Nov 9 at 15:44










  • @Neekoy Very good point, I'll add it in now. Glad to help
    – user184994
    Nov 9 at 15:44










  • Not sure this will only load the data once if more than one component subscribes to it.
    – Aviad P.
    Nov 9 at 16:29










  • @AviadP Having just played around with this, you're completely right, my mistake. @Neekoy I have made a change to use shareReplay instead of last, which should be more efficient. Please use that instead
    – user184994
    Nov 9 at 18:15















up vote
1
down vote



accepted










In your constructor, change the code like so:



  import { shareReplay } from 'rxjs/operators';

//...

constructor(private http: HttpClient) {
this.apiResult = this.dbConn.getApiRot().pipe(shareReplay());
}


By using the shareReplay operator, it will share the results among multiple subscribers, and replay the results. This way, your components can still subscribe:



  this.service.apiResult.subscribe(() => console.log("Done"))


But the data will only need to be loaded by the service once, on application load






share|improve this answer























  • Perfect - it does the trick and leaves only 1 line of logic in the other components which is what I was going for. I think it's worth mentioning that last() is contained in "import { last } from 'rxjs/operators';", other than that this is the correct answer. Thanks :)
    – Neekoy
    Nov 9 at 15:44










  • @Neekoy Very good point, I'll add it in now. Glad to help
    – user184994
    Nov 9 at 15:44










  • Not sure this will only load the data once if more than one component subscribes to it.
    – Aviad P.
    Nov 9 at 16:29










  • @AviadP Having just played around with this, you're completely right, my mistake. @Neekoy I have made a change to use shareReplay instead of last, which should be more efficient. Please use that instead
    – user184994
    Nov 9 at 18:15













up vote
1
down vote



accepted







up vote
1
down vote



accepted






In your constructor, change the code like so:



  import { shareReplay } from 'rxjs/operators';

//...

constructor(private http: HttpClient) {
this.apiResult = this.dbConn.getApiRot().pipe(shareReplay());
}


By using the shareReplay operator, it will share the results among multiple subscribers, and replay the results. This way, your components can still subscribe:



  this.service.apiResult.subscribe(() => console.log("Done"))


But the data will only need to be loaded by the service once, on application load






share|improve this answer














In your constructor, change the code like so:



  import { shareReplay } from 'rxjs/operators';

//...

constructor(private http: HttpClient) {
this.apiResult = this.dbConn.getApiRot().pipe(shareReplay());
}


By using the shareReplay operator, it will share the results among multiple subscribers, and replay the results. This way, your components can still subscribe:



  this.service.apiResult.subscribe(() => console.log("Done"))


But the data will only need to be loaded by the service once, on application load







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 9 at 18:14

























answered Nov 9 at 15:30









user184994

10.7k11526




10.7k11526












  • Perfect - it does the trick and leaves only 1 line of logic in the other components which is what I was going for. I think it's worth mentioning that last() is contained in "import { last } from 'rxjs/operators';", other than that this is the correct answer. Thanks :)
    – Neekoy
    Nov 9 at 15:44










  • @Neekoy Very good point, I'll add it in now. Glad to help
    – user184994
    Nov 9 at 15:44










  • Not sure this will only load the data once if more than one component subscribes to it.
    – Aviad P.
    Nov 9 at 16:29










  • @AviadP Having just played around with this, you're completely right, my mistake. @Neekoy I have made a change to use shareReplay instead of last, which should be more efficient. Please use that instead
    – user184994
    Nov 9 at 18:15


















  • Perfect - it does the trick and leaves only 1 line of logic in the other components which is what I was going for. I think it's worth mentioning that last() is contained in "import { last } from 'rxjs/operators';", other than that this is the correct answer. Thanks :)
    – Neekoy
    Nov 9 at 15:44










  • @Neekoy Very good point, I'll add it in now. Glad to help
    – user184994
    Nov 9 at 15:44










  • Not sure this will only load the data once if more than one component subscribes to it.
    – Aviad P.
    Nov 9 at 16:29










  • @AviadP Having just played around with this, you're completely right, my mistake. @Neekoy I have made a change to use shareReplay instead of last, which should be more efficient. Please use that instead
    – user184994
    Nov 9 at 18:15
















Perfect - it does the trick and leaves only 1 line of logic in the other components which is what I was going for. I think it's worth mentioning that last() is contained in "import { last } from 'rxjs/operators';", other than that this is the correct answer. Thanks :)
– Neekoy
Nov 9 at 15:44




Perfect - it does the trick and leaves only 1 line of logic in the other components which is what I was going for. I think it's worth mentioning that last() is contained in "import { last } from 'rxjs/operators';", other than that this is the correct answer. Thanks :)
– Neekoy
Nov 9 at 15:44












@Neekoy Very good point, I'll add it in now. Glad to help
– user184994
Nov 9 at 15:44




@Neekoy Very good point, I'll add it in now. Glad to help
– user184994
Nov 9 at 15:44












Not sure this will only load the data once if more than one component subscribes to it.
– Aviad P.
Nov 9 at 16:29




Not sure this will only load the data once if more than one component subscribes to it.
– Aviad P.
Nov 9 at 16:29












@AviadP Having just played around with this, you're completely right, my mistake. @Neekoy I have made a change to use shareReplay instead of last, which should be more efficient. Please use that instead
– user184994
Nov 9 at 18:15




@AviadP Having just played around with this, you're completely right, my mistake. @Neekoy I have made a change to use shareReplay instead of last, which should be more efficient. Please use that instead
– user184994
Nov 9 at 18:15


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53228403%2fget-result-from-httpget-request-in-getter-method-angular-7-service%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Guess what letter conforming each word

Port of Spain

Run scheduled task as local user group (not BUILTIN)