Issue
I'm running into a problem, and not an expert of async/rxjs development.
Let me explain my problem:
I have an angular service TimeoutService which only contains a processTimeout() method:
processTimeout(timeout: NodeJS.Timeout, stillLoading: boolean): void {
if (timeout !== undefined) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
if (stillLoading) this.dialog.open(LoadingDialogComponent);
}, this.TIMEOUT_DURATION_MS);
}
processTimeout() does the following:
Takes a
NodeJS.Timeoutas parameter, and astillLoadingboolean.first it checks if timeout is already on and clear it if so.
Then i set my timeout and if at the timeout callback the
stillLoadingvalue istrue(which always is because when i pass it as parameter to theprocessTimeoutmethod fromcomponentAthe value istrue), I open a dialog saying that request is taking to much time.
Problem is, the stillLoading boolean passed to method is an attribute of my standard angular components (for example lets call it ComponentA that has a boolean loadingA attribute ), and I already know that js/ts has pass-by-value for primitive types:
It is set to true when I call my api service and set to false when loading is completed (when subscribe to my api request has been done).
But setting the value of loadingA to false occurs after I call the processTimeout() method from my service.
- So my question is, what is the best way/ best practice so the boolean used in
processTimeout()stays a reference or pointer (the same for me but I do not really know how Js/Ts works behind the scenes, but a variable should have an internal memory / DOM Hex address) or even observable or something so the value ofstillLoadinginprocessTimeout()stays the same as my attributeloadingAof mycomponentA? (AttributeloadingAis passed asstillLoadingparameter and is also a primitivebooleantype incomponentA).
Because of the nature of the timeout that makes the code inside it execute after the timeout, i need the boolean value at that time (from the componentA), and not the value it was when passed-by-value in the method.
I'm down to listen to every possible solution, and if possible respecting ts and angular best practices.
- While writing the question, I also think I'll need the same solution for the timeout object too (But as it is an object it shall already be passed-by-reference right ?)
Thanks.
Tried: not a lot to be honest because I prefer some advice before losing hours on this problem, had an idea to pass a newly instanciated observable pointing on my componentA loadingA attribute, but I'm not sure at all of my comprehension of the way observables works for this kind of cases.
Expecting: the stillLoading method parameter in processTimeout being the same variable (same memory address) than my componentA loadingA boolean attribute, or any workaround solution/clues on tools i can use to fullfill my need.
Solution
METHOD 1:
The code does not necessarily need to be on the service, you can create a common class that two children inherit, that contain this code. This will ensure that the function has access to the component variables, because each child will have its own scope!
export class Common {
processTimeout(timeout: NodeJS.Timeout, stillLoading: boolean): void {
if (timeout !== undefined) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
if (stillLoading) this.dialog.open(LoadingDialogComponent);
}, this.TIMEOUT_DURATION_MS);
}
}
child
export class ParentA extends Common {
loading: false;
constructor(private timeoutService: TimeoutService) {
super()
}
ngOnInit() {
this.timeoutService(5000, this.loading);
this.loading = true;
}
}
This can be done with any number of children!
METHOD 2:
As you said you can pass by reference and ensure the service has the latest value!
In your component, you can call it like
export class ParentA {
loadingWrapper = {
loading: false,
}
constructor(private timeoutService: TimeoutService) {}
ngOnInit() {
this.timeoutService(5000, this.loadingWrapper);
this.loadingWrapper.loading = true;
}
}
in your service you can change it to
processTimeout(timeout: NodeJS.Timeout, stillLoadingWrapper: {loading: boolean}): void {
if (timeout !== undefined) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
if (stillLoadingWrapper.loading) this.dialog.open(LoadingDialogComponent);
}, this.TIMEOUT_DURATION_MS);
}
Answered By - Naren Murali
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.