2

I pretty sure this is a dumb question which is why I can't find the answer (or at least I hope it is a dumb quesiton with a quick answer). For some reason setTimeout is not working in one of my Angular 5 components. The relevant code looks like this:

onSubmit(...movieData) {
    this.movieService.addMovie(movieData)
        .subscribe(
            movie => {
                this.messageService.add("Movie Was Successfully added!")
                let title = movie['title'], year = movie['year']
                setTimeout(() => {
                    this.movieService.getMovie(title, year);
                }, 5000)
            },
            error => {
                console.log(error)
                this.messageService.add(error.error)
            }
        )
  }

As you can see from the code I'm trying to add a some movie data to a database. If the movie is successfully added I want to display a message for 5 seconds and the using setTimout, navigate to another page (Edit using the this.movieService(title, year) call End Edit). Well the message is displayed but nothing within the setTimeout function is run. I've even added console.log's before and within the setTimeout to confirm its the setTimeout thats not running. Anyone know what I'm doing wrong?

Stephen Agwu
  • 1,013
  • 2
  • 15
  • 29
  • 2
    You should terminate your statements with `;` character. Example: `this.messageService.add("Movie Was Successfully added!");` – Igor Mar 02 '18 at 14:21
  • About the navigation, I see nothing here that would execute navigation (including in the setTimeout callback). – Igor Mar 02 '18 at 14:22
  • 3
    @Igor no. using `;` is NOT mandatory - i never use them – messerbill Mar 02 '18 at 14:26
  • @messerbill It's not mandatory but avoiding them could lead to unexpected behaviors. – ADreNaLiNe-DJ Mar 02 '18 at 14:29
  • @ADreNaLiNe-DJ for example? it will behave exactly in the same way – messerbill Mar 02 '18 at 14:29
  • Sorry I wasn't clear about the navigation. The this.movieService.getMovie(title, year) executes a api call that leads to the router changing navigation elsewhere. – Stephen Agwu Mar 02 '18 at 14:31
  • @messerbill as long as you do not start a line with `(`, `[` or the back tick you are fine. [gotchas with omitting semicolons](https://standardjs.com/rules-en.html#semicolons) – t.niese Mar 02 '18 at 14:31
  • @StephenAgwu so your issue is fixed? - if yes, post the solution as an answer please – messerbill Mar 02 '18 at 14:32
  • 2
    @messerbill Take a look to this https://stackoverflow.com/a/1169596/5119765 – ADreNaLiNe-DJ Mar 02 '18 at 14:32
  • 1
    @ADreNaLiNe-DJ yes this is true - therefor you are right. But i always write my code inside of "framework given structures" (like express and angular) - so i nearly never come to this case! But i forgot it! Thank you very much – messerbill Mar 02 '18 at 14:35
  • 1
    I could see that possibly `movieService.getMovie` might not fire if this returns an observable that you do not subscribe to. I do not see how `console.log` statements would never appear in the browser though if you add them in your callback in `setTimeout`. Did you add a log statement before the `setTimeout` and one inside the `setTimeout` to see if at least one of those appears? – Igor Mar 02 '18 at 14:36
  • `using setTimout, navigate to another page`, but all I see is `this.movieService.getMovie(title, year)`. Are you sure you are routing ? –  Mar 02 '18 at 14:37
  • @Igor you should post your comment as an answer. Since there's no subscription on `getMovie`, there's nothing done. – ADreNaLiNe-DJ Mar 02 '18 at 14:38
  • @Igor, nice catch with the subscribable return, but I do place console logs both outside and inside the settimeout and they are never called... – Stephen Agwu Mar 02 '18 at 14:39
  • Have you attached your debugger? (*hint you can add the statement `debugger;` and if you have your browser development pane open your code will break when it reaches that statement*)? Walk though the code see if it reaches in and out of the `setTimeout` call (*break before and in*) – Igor Mar 02 '18 at 14:44
  • My guess would be that your scoped setTimeout is getting discarded. Try defining a variable in the root of your component, then `this.myTimeout = setTimeout(...)`. Or you can try using `function ()` instead of arrow handler which sets the instance reference to the subscription, and is likely why it doesn't get called. Hope this fixes your issue – Z. Bagley Mar 02 '18 at 14:48
  • Sorry friends but indeed I was making a silly mistake. I don't know why the function wasn't working initially but I since I'm running it with an express application I'm not watching the angular app but rather building and rebuilding changes. Well as you know you have to reload the application in the browser for the changes to have effect... I wasn't reloading the browser :/ – Stephen Agwu Mar 02 '18 at 14:56
  • @Igor, if you want to post your initial answer about the subsciption I'll accept that answer since it was probably the original mistake – Stephen Agwu Mar 02 '18 at 14:57

1 Answers1

1

movieService.getMovie might not fire if this returns an observable that you do not subscribe to. This is because most of the Observables returned from HttpClient are cold observables that do not execute until they are subscribed to.

See also HttpClient - Always subscribe

Igor
  • 60,821
  • 10
  • 100
  • 175