-2

Why can't I set an array instance variable from the ngOnInit method?

As you see in this screenshot, the last 2 console.log lines attempt to print the array. The first console.log prints the array with its 1 containing item. The second console.log outside of the .subscribe method prints an empty array as if the saved array is lost after the scope of the .subscribe method is done.

When my app loads, the list I am trying to display is empty because the array is empty.

enter image description here

Same as this question but NONE of the answers clarify it for me: Initializing properties inside ngOnInit scope

djangofan
  • 28,471
  • 61
  • 196
  • 289
  • 1
    I don't think it's to do with setting an array variable in `ngOnInit`. With having the rest of the `subscribe` method cut off, it's hard to tell, but it looks like this is expected behavior. At the point that the `console.log` outside of the `subscribe` method is executed, the observable hasn't emitted anything. Therefore, the subscription method hasn't been executed, and the array is empty. – Gregg L Apr 09 '21 at 00:47
  • 1
    I see what you mean. I am getting tripped up by component trying to load before my data has any value. So, I need to figure out how to get my component to wait. – djangofan Apr 09 '21 at 01:00

2 Answers2

1

It helps to know that the callback functions are not executed where they are declared. Angular manages the Observables outside the context of your component. The callback function in the subscribe function declared there in the ngOnInit will be run by angular every time the observable returned from the getChannelStatsById() function emits a value. Even after the ngOnInit has long completed.

When the callback function executes, the rowData value will be set and the HTML template should update automatically. An *ngIf check can also be used to see if you have values before displaying the data

<ng-container *ngIf="rowData?.length > 0">
  {{ rowData }}
</ng-container>

I am assuming the getChannelStatsById() function makes an HTTP call in which case it returns an observable that will most probably emit only one value on a successful response from the HTTP call. But it is possible to configure http calls to emit multiple values too. The flow of execution in the component creation or the lifecycle hook like the ngOnInit function does not stop for the observable to emit a value.

Also, very important to remember is observables can emit values indefinitely and angular may keep executing those callback functions after the component has been destroyed. Using async pipe in the HTML template would make life easy as angular handles the subscription OR unsubscribing in the ngOnDestroy lifecycle hook.

C J
  • 46
  • 5
  • Most of your answer was just telling me stuff I already knew, but your idea of using rowData.length > 0 on a ngIf fixed it for me. Thank you. I tried setting a boolean variable and using ngIf and that didn't work for me. SO, thanks for your alternate suggestion. Much appreciated. – djangofan Apr 09 '21 at 16:07
0

The method subscribes to an observable and essentially asks for a result, then it moves on and prints an initially empty array, THEN the result comes back and the array gets the result pushed to it, as seen in the following console.log. This is just how asynchronous javascript works.

Carson
  • 36
  • 2