Angular 4 - Can OnDestroy be run without the OnInit ever being triggered?

Viewed 2166

Just a generic question regarding the two Lifecycle Hooks OnInit and OnDestroy. As this article mentions, I had always assumed that OnInit is always run before the OnDestroy.

I have a case where in an ngOnDestroy() I'm stopping a background music track from playing. This sound is loaded the component's ngOnInit(), and because the ngOnDestroy() is being run without the ngOnInit() being run the sound object is undefined.

Code

ngOnInit() {
    ...

    this.loadSounds();

    ...
}

ngOnDestroy() {
    if (AppSettings.SOUNDS_ENABLED) {
        this.soundService.getSound(Sound.MINI_GAME_BG_MUSIC).fade(0.2, 0, 1500);
    }
}

private loadSounds() {
    this.soundService.loadSound(Sound.MINI_GAME_BG_MUSIC, SoundPathURL.MINI_GAME_BG_MUSIC, true, 0);
}

At the moment the code is failing in the ngOnDestroy when trying to .fade() a sound that's undefined. Of course I can easily fix this by checking that the sound is not undefined before executing the .fade() function. My assumption was that if an ngOnDestroy() is run the ngOnInit() must have been run as well - I guess I was wrong.

Now because of this case I'm thinking that in every ngOnDestroy() in my application I should check whether the object being used is undefined before performing any operations. So for example before unsubscribing from a subscription I should check if the subscription is undefined, and so on.

Am I right to assume so?

1 Answers

The reference clearly states that OnInit lifecycle hook precedes OnDestroy. This behaviour is specific to the compiler in general. The article explains the behaviour that is specific to Angular router and the way <router-outlet> directive instantiates components. router.navigateByUrl() in route component constructor triggers its immediate destruction and prevents it from being compiled, so the lifecycle isn't applicable to it. This won't happen under normal circumstances.

The code in the question doesn't imply that ngOnInit doesn't run. ngOnInit call be easily logged to prove that it runs.

The service that is used by this component can cause the problem. The fact that Cannot read property 'fade' of undefined or similar error is thrown in ngOnDestroy means that this.soundService.getSound(Sound.MINI_GAME_BG_MUSIC) is undefined.

This totally depends on what happens inside soundService service. If loadSound is asynchronous, and ngOnDestroy was called before a resource was loaded, there may be problems.

Related