I'm trying to build a timer using Vue.js and I want it to output the time left.
new Vue({
el: "#app",
data: {
timer: 25,
message2: "",
counter: false,
interval: null
},
methods: {
startTimer() {
this.interval = setInterval(this.countDown(), 1000);
},
countDown() {
if (this.counter === false) {
var n = this.timer;
this.counter = true;
} else if (n > 0) {
n -= 1;
this.message2 = "You have " + n + "seconds left.";
} else {
clearInterval(this.interval);
this.counter = false;
this.message2 = "Your time is up!"
}
},
But I cannot get the message2
updated every time Interval runs the function countDown()
. Actually it doesn't run the function every second but only once.
I'm trying to build a timer using Vue.js and I want it to output the time left.
new Vue({
el: "#app",
data: {
timer: 25,
message2: "",
counter: false,
interval: null
},
methods: {
startTimer() {
this.interval = setInterval(this.countDown(), 1000);
},
countDown() {
if (this.counter === false) {
var n = this.timer;
this.counter = true;
} else if (n > 0) {
n -= 1;
this.message2 = "You have " + n + "seconds left.";
} else {
clearInterval(this.interval);
this.counter = false;
this.message2 = "Your time is up!"
}
},
But I cannot get the message2
updated every time Interval runs the function countDown()
. Actually it doesn't run the function every second but only once.
-
1
You're executing
undefined
in setInterval because you're calling your countDown method which doesn't return a function. – Wabbitseason Commented Jun 9, 2017 at 9:34 - I'm not sure that I understand. I've always thought of methods as functions. – Yanek Yuk Commented Jun 9, 2017 at 9:37
-
this.interval = setInterval(this.countDown, 1000);
remove the () from the function.setInterval
is expecting a function as 1st parameter. That means you pass it a function reference likethis.countDown
or declare an anonymous function likefunction() { //dostuff}
. Check this out for further information about function calls/references: stackoverflow./questions/15886272/… – xetra11 Commented Jun 9, 2017 at 9:42
2 Answers
Reset to default 4You should pass a function to setInterval
, but since you execute this.countDown
immediatly, you are passing the result of that call to setInterval
:
startTimer() {
this.interval = setInterval(this.countDown(), 1000);
}
to pass the function instead of calling it, leave out the ()
startTimer() {
this.interval = setInterval(this.countDown, 1000);
}
also, I fixed some mistakes in countdown()
(e.g. defining n
in the if
branch, but using it in the else if
, so it's undefined
there, or only changing the local n
, which would not change this.timer
...)
countDown() {
var n = this.timer
if (!this.counter) {
this.counter = true;
} else if (n > 0) {
n = n - 1
this.timer = n
this.message2 = "You have " + n + "seconds left."
} else {
clearInterval(this.interval);
this.counter = false
this.message2 = "Your time is up!"
}
},
As others have pointed out, you need to pass your function to setInterval, not invoke it and pass its return value.
Furthermore, when you execute the statement n = this.timer
, you are invoking the getter that Vue set up on this.timer and copying the very unmagical number 25 to your variable n
. n
then goes out of scope when the function returns and your copy of 25 is lost. The next time your function runs (another second later) n
is undefined. This results in your else clause clearing the interval. Your elseif clause never runs.
I think the smallest change to make your code work would be to promote n
to live in your data: add n: undefined,
to your data:{}, so that it can be tracked by Vue, then replace all your uses of n
with this.n
.
Once you've got that working, I'd remend simplifying some things:
- setting
this.n = this.timer
should probably be done in startTimer - if you set
this.interval = undefined
when you clear your interval,this.counter
bees redundant, because you can just check ifthis.interval
is truthy - you can turn message2 into a "puted"
- you can add an if clause to startTimer to prevent a second interval from being added if there's already one active (e.g. if someone clicks a "start timer" button twice before the timer runs down)