Vue.js destroy a setInterval running inside a component
Asked Answered
E

5

7

In my SPA made with VUE I have a component running a recursive few of setInterval functions (it's a countdown). I noticed the countdown continue in the background when I switch view to another component, but I prefer to destroy the setInterval.

I tried using a global data having the countdowns and then destroy it on destroyed hook but it doesn't work.

Here my code:

    data: function () {
        return {
            counters: ""
        }
    }),

   methods: {
     countdown(index, exp) {
        ...
          this.counters = setInterva()
        ...
        },
   },

   destroyed(){
        console.log(this.counters); // returns a progressive integer
        clearInterval(this.counters);
        console.log(this.counters); // returns same integer
        this.counters = 0;
        console.log("destroyed");
    } 

But in the console I got:

destroyed

app.js:64433 0

app.js:64398 Missing counter_1 . <--- which means counter is still running

Thanks for any suggestion!

Etti answered 23/8, 2019 at 7:37 Comment(7)
Put your destroyed function adjacent to methods. not inside methods.Convenance
Yes, it is. Just fixed the typo in the post.Etti
Can you share the entire code of the coundown method? I wonder if this when you use it inside of the method might actually not refer to the vue instance (a context problem?) so that when you reference it in the destroyed hook it might not be assigned to that variable. Have you tried to console log this.counters in the destroyed hook? Is it defined?Escobedo
@TobiasG. The countdown method contains only the setInterval function. I have tried to log the this.counters value in the last hook before and after the clearInterval: it it an integer (progressive) before and same value after clearInterval.Etti
Please share all your component code. I think the issue can be you call countdown multiple times and you just cleanup the last. If that is correct, you should convert counters to an array of task ids to clean up and then clean in a loop. Or protect the invocation of the setInterval cleanup the last scheduled task before starting a new one.Anthelion
Maybe a solution could be here: #19970899Etti
What @MarioSantini said, i just entered your code above into jsfiddle and could not find any issue why it wouldn't work, so i think it's very likely that your problem is in an area of your code that you did not share yet.Escobedo
G
6

In vue3 destroy() and beforeDestroy() has been deprecated.

Use unmount() or beforeUnmount() instead.

beforeUnmount(){
    clearInterval(this.counters);
}
Gloucester answered 2/8, 2021 at 14:3 Comment(0)
C
4

There might be two things happening here depending on if you are calling countdown or not:

1. countdown is not called

countdown(index, exp) needs to be defined in the created hook such as below. Furthermore, a method foo() should be bound to this interval for the expected functionality.

  created: function(){
      this.counterInterval =  setInterval(
        function()
        {
          this.foo();
        }.bind(this), 500);
    return this.foo();
  },
  destoyed: function(){
    clearInterval( this.counterInterval )
  },

2. countdown is called properly but the component is actually not getting destroyed

If the error is actually a misunderstanding on what it means to "destroy" the component, such that the component is not getting destroyed, the same code as above can be used, but a data prop of isShowing: true bounded within the JSX will solve the problems.

Just do a v-if check on isShowing and then do an event listener if the element is in view. If the element is in view, then we have isShowing===true. else, false.

Comedian answered 13/11, 2019 at 19:47 Comment(1)
you have misspelled the word "destroyed"Cadman
M
1

You should use beforeDestroy hook instead of destroyed

For reference on vue lifecycle check out https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

Murdocca answered 23/8, 2019 at 9:37 Comment(2)
the destroyed hook still has access to thisof the instance so this should not be the problem. See here: jsfiddle.net/tbgse/ck5zw4mu/2Escobedo
Learn something new every day, Thanks! @TobiasG.Murdocca
V
0

Try this Change destroyed() method to beforeDestroy().

update

maybe vue component did not destroy. try destroy manually

sorry for my bad English

Voice answered 23/8, 2019 at 9:35 Comment(1)
the destroyed hook still has access to thisof the instance so this should not be the problem. See here: jsfiddle.net/tbgse/ck5zw4mu/2Escobedo
T
0

Use beforeRouteLeave route navigation guard inside route components to destroy setInterval. Add clearInterval function inside beforeRouteLeave, this will destroy the timer set by setInterval before we leave the component

beforeRouteLeave (to, from, next) {
    clearInterval(this.counters);
    next()
},
Turbit answered 4/6, 2021 at 5:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.