Angular service is undefined when fetching backend data in its constructor
I have a SessionService
which manages JWT token and stores user data. When my app is started I need to fetch user data from backend via http. It might be a bad idea, but since there is no ngOnInit()
for services I do it in SessionService
constructor:
@Injectable({
providedIn: 'root'
})
export class SessionService {
constructor(
private errHandler: ErrorHandlingService,
private backend: UsersService
) {
const initialToken = this.rawToken; // localStorage.getItem('jwt')
if (!initialToken || this.isTokenExpired(initialToken)) {
localStorage.removeItem('jwt');
return;
}
this.fetchUser();
}
private fetchUser() {
this.backend.getMe().subscribe(
user => this.user = user,
err => this.errHandler.handle(err)
);
}
/* ... */
}
I think this is pretty straightforward, UsersSevice::getMe()
is just an abstraction for:
getMe() {
return this.http.get<Api.V1.Me.Get.Response>('/api/v1/me');
}
The problem is that my HttpInterceptor
that attaches JWT to the header of each http request, that it obtains via my SessionService
gets this service as undefined
, so the TypeError
is raised when accessing its rawRoken
getter (can not read property rawToken of undefined
)
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private session: SessionService) {}
intercept(req: HttpRequest<unknown>, next: HttpHandler) {
const rawToken = this.session.rawToken;
/* ... */
}
}
I have found a workaround to wrap my this.fetchUser()
call with setTimeout(() => this.fetchUser(), 0)
, but why do I have to postpone this to another turn of event loop? That is my question. Please tell me, what rule am I violating?
angular angular-services angular-httpclient angular-http-interceptors angular7
add a comment |
I have a SessionService
which manages JWT token and stores user data. When my app is started I need to fetch user data from backend via http. It might be a bad idea, but since there is no ngOnInit()
for services I do it in SessionService
constructor:
@Injectable({
providedIn: 'root'
})
export class SessionService {
constructor(
private errHandler: ErrorHandlingService,
private backend: UsersService
) {
const initialToken = this.rawToken; // localStorage.getItem('jwt')
if (!initialToken || this.isTokenExpired(initialToken)) {
localStorage.removeItem('jwt');
return;
}
this.fetchUser();
}
private fetchUser() {
this.backend.getMe().subscribe(
user => this.user = user,
err => this.errHandler.handle(err)
);
}
/* ... */
}
I think this is pretty straightforward, UsersSevice::getMe()
is just an abstraction for:
getMe() {
return this.http.get<Api.V1.Me.Get.Response>('/api/v1/me');
}
The problem is that my HttpInterceptor
that attaches JWT to the header of each http request, that it obtains via my SessionService
gets this service as undefined
, so the TypeError
is raised when accessing its rawRoken
getter (can not read property rawToken of undefined
)
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private session: SessionService) {}
intercept(req: HttpRequest<unknown>, next: HttpHandler) {
const rawToken = this.session.rawToken;
/* ... */
}
}
I have found a workaround to wrap my this.fetchUser()
call with setTimeout(() => this.fetchUser(), 0)
, but why do I have to postpone this to another turn of event loop? That is my question. Please tell me, what rule am I violating?
angular angular-services angular-httpclient angular-http-interceptors angular7
Sounds like your sessions service hasn't be instantiated yet by the time it's called in your service. At what point of your applications lifecycle does that happen? It's definitely a timing issue.
– Mickers
Nov 21 '18 at 20:49
@Mickers I've suddenly realized why this happens. Its because I do an http request in my SessionService constructor and my http interceptor is called synchronously for that request, but I haven't escaped my SessionService constructor function yet. Yeah, that was unexpected. My SessionService and JwtInterceptor just have implicit circular dependency through the HttpClient.
– Veetaha
Nov 21 '18 at 20:54
Glad that helped
– Mickers
Nov 21 '18 at 20:56
add a comment |
I have a SessionService
which manages JWT token and stores user data. When my app is started I need to fetch user data from backend via http. It might be a bad idea, but since there is no ngOnInit()
for services I do it in SessionService
constructor:
@Injectable({
providedIn: 'root'
})
export class SessionService {
constructor(
private errHandler: ErrorHandlingService,
private backend: UsersService
) {
const initialToken = this.rawToken; // localStorage.getItem('jwt')
if (!initialToken || this.isTokenExpired(initialToken)) {
localStorage.removeItem('jwt');
return;
}
this.fetchUser();
}
private fetchUser() {
this.backend.getMe().subscribe(
user => this.user = user,
err => this.errHandler.handle(err)
);
}
/* ... */
}
I think this is pretty straightforward, UsersSevice::getMe()
is just an abstraction for:
getMe() {
return this.http.get<Api.V1.Me.Get.Response>('/api/v1/me');
}
The problem is that my HttpInterceptor
that attaches JWT to the header of each http request, that it obtains via my SessionService
gets this service as undefined
, so the TypeError
is raised when accessing its rawRoken
getter (can not read property rawToken of undefined
)
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private session: SessionService) {}
intercept(req: HttpRequest<unknown>, next: HttpHandler) {
const rawToken = this.session.rawToken;
/* ... */
}
}
I have found a workaround to wrap my this.fetchUser()
call with setTimeout(() => this.fetchUser(), 0)
, but why do I have to postpone this to another turn of event loop? That is my question. Please tell me, what rule am I violating?
angular angular-services angular-httpclient angular-http-interceptors angular7
I have a SessionService
which manages JWT token and stores user data. When my app is started I need to fetch user data from backend via http. It might be a bad idea, but since there is no ngOnInit()
for services I do it in SessionService
constructor:
@Injectable({
providedIn: 'root'
})
export class SessionService {
constructor(
private errHandler: ErrorHandlingService,
private backend: UsersService
) {
const initialToken = this.rawToken; // localStorage.getItem('jwt')
if (!initialToken || this.isTokenExpired(initialToken)) {
localStorage.removeItem('jwt');
return;
}
this.fetchUser();
}
private fetchUser() {
this.backend.getMe().subscribe(
user => this.user = user,
err => this.errHandler.handle(err)
);
}
/* ... */
}
I think this is pretty straightforward, UsersSevice::getMe()
is just an abstraction for:
getMe() {
return this.http.get<Api.V1.Me.Get.Response>('/api/v1/me');
}
The problem is that my HttpInterceptor
that attaches JWT to the header of each http request, that it obtains via my SessionService
gets this service as undefined
, so the TypeError
is raised when accessing its rawRoken
getter (can not read property rawToken of undefined
)
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private session: SessionService) {}
intercept(req: HttpRequest<unknown>, next: HttpHandler) {
const rawToken = this.session.rawToken;
/* ... */
}
}
I have found a workaround to wrap my this.fetchUser()
call with setTimeout(() => this.fetchUser(), 0)
, but why do I have to postpone this to another turn of event loop? That is my question. Please tell me, what rule am I violating?
angular angular-services angular-httpclient angular-http-interceptors angular7
angular angular-services angular-httpclient angular-http-interceptors angular7
edited Nov 21 '18 at 19:49
Veetaha
asked Nov 21 '18 at 19:38


VeetahaVeetaha
101111
101111
Sounds like your sessions service hasn't be instantiated yet by the time it's called in your service. At what point of your applications lifecycle does that happen? It's definitely a timing issue.
– Mickers
Nov 21 '18 at 20:49
@Mickers I've suddenly realized why this happens. Its because I do an http request in my SessionService constructor and my http interceptor is called synchronously for that request, but I haven't escaped my SessionService constructor function yet. Yeah, that was unexpected. My SessionService and JwtInterceptor just have implicit circular dependency through the HttpClient.
– Veetaha
Nov 21 '18 at 20:54
Glad that helped
– Mickers
Nov 21 '18 at 20:56
add a comment |
Sounds like your sessions service hasn't be instantiated yet by the time it's called in your service. At what point of your applications lifecycle does that happen? It's definitely a timing issue.
– Mickers
Nov 21 '18 at 20:49
@Mickers I've suddenly realized why this happens. Its because I do an http request in my SessionService constructor and my http interceptor is called synchronously for that request, but I haven't escaped my SessionService constructor function yet. Yeah, that was unexpected. My SessionService and JwtInterceptor just have implicit circular dependency through the HttpClient.
– Veetaha
Nov 21 '18 at 20:54
Glad that helped
– Mickers
Nov 21 '18 at 20:56
Sounds like your sessions service hasn't be instantiated yet by the time it's called in your service. At what point of your applications lifecycle does that happen? It's definitely a timing issue.
– Mickers
Nov 21 '18 at 20:49
Sounds like your sessions service hasn't be instantiated yet by the time it's called in your service. At what point of your applications lifecycle does that happen? It's definitely a timing issue.
– Mickers
Nov 21 '18 at 20:49
@Mickers I've suddenly realized why this happens. Its because I do an http request in my SessionService constructor and my http interceptor is called synchronously for that request, but I haven't escaped my SessionService constructor function yet. Yeah, that was unexpected. My SessionService and JwtInterceptor just have implicit circular dependency through the HttpClient.
– Veetaha
Nov 21 '18 at 20:54
@Mickers I've suddenly realized why this happens. Its because I do an http request in my SessionService constructor and my http interceptor is called synchronously for that request, but I haven't escaped my SessionService constructor function yet. Yeah, that was unexpected. My SessionService and JwtInterceptor just have implicit circular dependency through the HttpClient.
– Veetaha
Nov 21 '18 at 20:54
Glad that helped
– Mickers
Nov 21 '18 at 20:56
Glad that helped
– Mickers
Nov 21 '18 at 20:56
add a comment |
0
active
oldest
votes
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',
autoActivateHeartbeat: false,
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53419405%2fangular-service-is-undefined-when-fetching-backend-data-in-its-constructor%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53419405%2fangular-service-is-undefined-when-fetching-backend-data-in-its-constructor%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
Sounds like your sessions service hasn't be instantiated yet by the time it's called in your service. At what point of your applications lifecycle does that happen? It's definitely a timing issue.
– Mickers
Nov 21 '18 at 20:49
@Mickers I've suddenly realized why this happens. Its because I do an http request in my SessionService constructor and my http interceptor is called synchronously for that request, but I haven't escaped my SessionService constructor function yet. Yeah, that was unexpected. My SessionService and JwtInterceptor just have implicit circular dependency through the HttpClient.
– Veetaha
Nov 21 '18 at 20:54
Glad that helped
– Mickers
Nov 21 '18 at 20:56