Vue clearInterval cant stop timer (reset timer) - vuejs2

I try to write function to restart setInterval timer:
data() {
return {
intervalId: undefined,
backlightTimerSeconds: 5000,
}
},
I have an method:
timerBacklightOff() {
const interval = 1000
this.intervalId = setInterval(() => {
this.backlightTimerSeconds -= interval
console.log('timerBacklightOff', this.backlightTimerSeconds)
if(this.backlightTimerSeconds <= 0) {
this.setBacklight(false)
this.clearTimerBacklight()
return
}
}, interval)
},
In antoher method I have method to clear interval:
clearTimerBacklight() {
if(!this.intervalId) return
this.backlightTimerSeconds = 0
clearInterval(this.intervalId)
this.intervalId = undefined
this.backlightTimerSeconds = 5000
},
I runned method clearTimerBacklight using button.
I have a problem, blecause when I running method clearTimerBacklight, then not stop setInterval and console.log('timerBacklightOff', this.backlightTimerSeconds) still counter down. How I can restart setInterval to basis time?

Related

realtime clock with vue js

I've written a small clock component for one of my projects,
but I didn't get the value for my clock refreshed.
A short extract of my code:
time() {
let now = new Date();
let hour = this.zeroPadding(now.getHours());
let minute = this.zeroPadding(now.getMinutes());
let second = this.zeroPadding(now.getSeconds());
console.log(hour.toString() + minute.toString() + second.toString())
if(!this.realtime)
return this.value
else
return hour.toString() + ":" + minute.toString() + ":" + second.toString()
}
},
mounted() {
setInterval(() => {
this.time()
}, 1000)
},
beforeDestroy () {
clearInterval(this.polling)
}
Does anyone finde the mistake?
Did I understand the polling wrong?
Greetings,
Matthias
The time value that you want to display needs to be a data / computed property so that it's reactive and Vue can track it. Concise way to do it:
export default {
data() {
return {
interval: null,
time: null
}
},
beforeDestroy() {
// prevent memory leak
clearInterval(this.interval)
},
created() {
// update the time every second
this.interval = setInterval(() => {
// Concise way to format time according to system locale.
// In my case this returns "3:48:00 am"
this.time = Intl.DateTimeFormat(navigator.language, {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
}).format()
}, 1000)
}
}

Vuex can't stop setInteval

I have a method in Vuex:
export const startTime = ({ commit, state }, status) => {
let timeInterval
if(status) {
const timer = 1000
timeInterval = setInterval(() => {
console.log('x')
commit('SET_RUNNED_TIME', parseInt(state.runnedTime += timer))
}, timer)
}
else {
console.log('y')
clearInterval(timeInterval)
commit('SET_RUNNED_TIME', 0)
}
}
From my component I send value true or false to method startTime(). When I send true then method run commit SET_RUNNED_TIME. But when I send false clearInterval(timeInterval) not stopping setInterval and still is sending commit('SET_RUNNED_TIME' ...)
The variable timeInterval is inside the scope of the function. If you want it to keep on living between different calls to startTime you need to put it outside the function scope. For example in the state.

React Native - start Animated twice, an error start of undefined

animation = new Animated.Value(0);
animationSequnce = Animated.sequence(
[Animated.timing(this.animation, { toValue: 1 }),
Animated.timing(this.animation, { toValue: 0, delay: 1000 }),
],
);
startAnimation = () => {
animationSequnce.start();
}
stopAnimation = () => {
animationSequnce.stop();
}
I want to start an animation sequence several times.
I tested it by writing code that calls startAnimation when the button is pressed.
The animation runs on the first run.
When the second button is clicked after the first animation is finished
Cannot read property 'start' of undefined error occurs.
startAnimation = () => {
Animated.sequence(
[Animated.timing(this.animation, { toValue: 1 }),
Animated.timing(this.animation, { toValue: 0, delay: 1000 }),
],
).start();
}
This change to startAnimation will not cause an error, but you will not be able to call stopAnimation because it will call a different AnimationSequnce each time.
What is the best way to use an animation multiple times?
to stop animation
this.animation.stopAnimation()
optional get callBack when the animation stop
this.animation.stopAnimation(this.callback())
or
Animated.timing(
this.animation
).stop();
The first time you call Animated.sequence(), react native creates a variable current, refers to the index of the current executing animation, and stores it locally.
When Animated.sequence().start() finished, the variable current won't be cleaned or reset to 0, so the second time you call start() on the same sequenced animation, the array index out of bound and cause error.
It's a hidden bug of react native, below is the implementation of Animated.sequence
const sequence = function(
animations: Array<CompositeAnimation>,
): CompositeAnimation {
let current = 0;
return {
start: function(callback?: ?EndCallback) {
const onComplete = function(result) {
if (!result.finished) {
callback && callback(result);
return;
}
current++;
if (current === animations.length) {
callback && callback(result);
return;
}
animations[current].start(onComplete);
};
if (animations.length === 0) {
callback && callback({finished: true});
} else {
animations[current].start(onComplete);
}
},
stop: function() {
if (current < animations.length) {
animations[current].stop();
}
},
reset: function() {
animations.forEach((animation, idx) => {
if (idx <= current) {
animation.reset();
}
});
current = 0;
},
_startNativeLoop: function() {
throw new Error(
'Loops run using the native driver cannot contain Animated.sequence animations',
);
},
_isUsingNativeDriver: function(): boolean {
return false;
},
};
};
My solution is to define a custom sequence, and manually reset current to 0 when the sequenced animations finished:
const sequence = function(
animations: Array<CompositeAnimation>,
): CompositeAnimation {
let current = 0;
return {
start: function(callback?: ?EndCallback) {
const onComplete = function(result) {
if (!result.finished) {
current = 0;
callback && callback(result);
return;
}
current++;
if (current === animations.length) {
current = 0;
callback && callback(result);
return;
}
animations[current].start(onComplete);
};
if (animations.length === 0) {
current = 0;
callback && callback({finished: true});
} else {
animations[current].start(onComplete);
}
},
stop: function() {
if (current < animations.length) {
animations[current].stop();
}
},
reset: function() {
animations.forEach((animation, idx) => {
if (idx <= current) {
animation.reset();
}
});
current = 0;
},
_startNativeLoop: function() {
throw new Error(
'Loops run using the native driver cannot contain Animated.sequence animations',
);
},
_isUsingNativeDriver: function(): boolean {
return false;
},
};
};

Countdown variable (HH:mm:ss)

I parse a date YYYY-mm-dd and calculate the difference till midnight. The result will be always under 24h, for example 10:01:10 - HH:mm:ss till it expires. I wonder how I could achieve a countdown functionality with the given example.
<template>
<Label :text="date.expires | readableTime"></Label>
</template>
filters: {
readableTime(value) {
var now = moment(new Date());
var end = moment(value);
var diff = moment.duration(end.diff(now));
try {
return moment.utc(diff.as("milliseconds")).format("HH:mm:ss");
} catch (e) {
return "00:00:00";
}
}
}
You must use use timer and reactive data property. I recommend you to safe diff to components data, start timer on component mount and clear it beforeDestroy
data() {
return {
diff: this.calculareDiff()
}
}
methods: {
calculareDiff() {
const now = moment(new Date());
const end = moment(this.date.expires);
this.diff = moment.duration(end.diff(now));
}
},
mounted() {
this.timer = setInterval(() => this.calculareDiff(), 1000)
},
beforeDestroy() {
clearInterval(this.timer)
}

VueJS: setInterval method not working properly

Please tell me what am i doing wrong? I want to active 'cloth' update every 2 sec. Still learning vue. Thanks
data() {
return {
clothes: ['t-shirts', 'sneakers', 'jackets'],
count: 0,
cloth: ''
}
},
methods: {
startInterval() {
setInterval(() => {
this.cloth = this.clothes[this.count]
this.count++
if (this.count >= this.clothes.length) {
this.count = 0;
}
}, 2000)
}
}
Vue has a life cycle that you can leverage to complete this objective. You can hook into the created function and execute your interval within:
created() {
this.startInterval()
},
This is not a method. It will be a sibling to your data and method properties.