problems with clearTimeout() in vue.js - javascript

i'm doing a shopping cart in vue but i'm having some issues. having never used the library i'm probably doing basics wrong, but:
when I add something to the cart I have an onclick function, expander(item) which looks like this:
this.addToCart(item);
this.show = true;
clearTimeout(this.timer);
timer: setTimeout(()=>{ this.show = false; }, 3000);
so what it does it adds to cart, sets the visibility of the cart div to true, then after a delay of three seconds it sets the cart div back to false.
the thing is, the clearTimeout(this.timer) doesn't work. so for each click, after three seconds, no matter what I do it sets the visibility back to false. what I'm trying to do with this function is to reset the timer each time and after reading up it seems like I'm doing it the correct way.
so, I'm guessing my problem is that i need to declare the variable
timer: setTimeout(()=>{ this.show = false; }, 3000);
outside of the function, in order for clearTimeout() to find it at the beginning of my function. my problem here is that wherever I declare it, it can't seem to find it. I've tried declaring the variable in my data {} and also outside of the Vue instance but it doesn't seem to want to find it in my functions.
so: how do I declare the variable? is that even my problem? is there may be an easier fix for this than what it's trying to do?
thanks!

In the quoted code, this line:
timer: setTimeout(()=>{ this.show = false; }, 3000);
defines a labelled statement, and doesn't save the timer handle anywhere. To save it to this.timer, you'd use an assignment:
this.timer = setTimeout(()=>{ this.show = false; }, 3000);
(The timer: thing would assign to a property within an object initializer [{ ... }], but not outside of one.)

wait 1 second between keypress,
if user keypress, clear setTimeout and renew setTimeout with more 1 second
after 1 second user dont keypress the before setTimeout expire and call another function(method in VueJs)
List item
I used this solution, it's verify if user end the word before call api:
data: {
search: '',
time:null,
},
watch: {
search: function (search) {
var self = this;
console.log('Search keypress: ' + search);
if (search.length >= 3) {
if (this.time) {
clearTimeout(this.time);
}
this.time = setTimeout( () => this.searchOnline(search), 1000);
console.log('Search online or wait user finish word?');
}
},
},
methods:{
searchOnline: function(search){
console.log('Start search online: ' + search);
// axios call api search endpoint
console.log('Serch online finished!');
},
}

setTimeout generates an id
capture this id in a variable
pass this variable to clearTimeout
as per MDN: The returned timeoutID is a positive integer value which identifies the timer created by the call to setTimeout(); this value can be passed to clearTimeout() to cancel the timeout.
In Vuejs the following steps work for me.
data: {
myToid:null,
}, ....
methods: {
myTofunction: function(){
clearTimeout(this.myToid);
this.myToid = setTimeout(() => {
...my function code...;
}, 6000);
}
}
Whenever I call myTofunction, it first clears any existing setTimeout id (stored in myToid) and then sets a new id.

Related

setTimeout() function is not detecting a state change and keeps executing the recursive function

useEffect(() => {
playLoop();
}, [state.playStatus]);
const playLoop = () => {
if (state.playStatus) {
setTimeout(() => {
console.log("Playing");
playLoop();
}, 2000);
} else {
console.log("Stopped");
return;
}
};
Output:
Stopped
// State Changed to true
Playing
Playing
Playing
Playing
// State Changed to false
Stopped
Playing // This is the problem, even the state is false this still goes on execute the Truthy stalemate
Playing
Playing
I am working on react-native and I want the recursion to stop when the state value becomes false.
Is there any other way I can implement this code I just want to repeatedly execute a function while the state value is true.
Thank you
Rather than having a playStatus boolean, I'd save the interval ID. That way, instead of setting playStatus to false, call clearInterval. Similarly, instead of setting playStatus to true, call setInterval.
// Can't easily use useState here, because you want
// to be able to call clearInterval on the current interval's ID on unmount
// (and not on re-render) (interval ID can't be in an old state closure)
const intervalIdRef = useRef(-1);
const startLoop = () => {
// make sure this is not called while the prior interval is running
// or first call clearInterval(intervalIdRef.current)
intervalIdRef.current = setInterval(
() => { console.log('Playing'); },
2000
);
};
const stopLoop = () => {
clearInterval(intervalIdRef.current);
};
// When component unmounts, clean up the interval:
useEffect(() => stopLoop, []);
The first thing you should do is make sure to clear the timeout when the state changes to stopped or otherwise check the state within the timeout callback function.
But the problem does not seem to be with the setTimeout code only by itself, but rather that this playLoop is also being called too many times. You should add a console.log with a timestamp right at the start of your playLoop to confirm or disprove this. And to find out where it is called from, you could use console.trace.
const playLoop = () => {
console.log(new Date(), ': playLoop called')
console.trace(); // optional
if (state.playSt....

Javascript variable function does not persist values

This js function is part of a global variable. The first time it is called, from another js file, it works. But the second time, from itself, everything null.
Start: function () {
console.log('InactivityAlerts.Start() called ...');
if (this.active) {
if (this.IDLE_TIMEOUT != "") {
window.setInterval(this.CheckIdleTime, 1000);
console.log('started...');
}
else {
window.setTimeout(this.Start, 1000);
//an iframe sets the IDLE_TIMEOUT later, but this should continue to
//run until it is not blank.
}
}
},
When it calls itself again; however, everything is null, including this.active which was set from an Init prior to this. Why? And how can I make sure everything is still set right?
Thanks for any help
It's a this value issue, make sure you are binding the correct this value when passing functions around.
window.setInterval(this.CheckIdleTime.bind(this), 1000);
window.setTimeout(this.Start.bind(this), 1000);
You can also bind these at construction time if you always want them bound to the same instance.
function YourConstructor() {
//assumes that someFunction is defined on YourConstructor.prototype
this.someFunction = this.someFunction.bind(this);
}
Or the same with a well-known instance:
InactivityAlerts = {
Start: function () { /*...*/ }
};
InactivityAlerts.Start = InactivityAlerts.Start.bind(InactivityAlerts);

overwriting setInterval

I thought in the past that if I create a variable that I can overwrite them simple.
I'am trying to do the following:
var zoom = {
$el : $('#Overlay'),
nextTimer : null,
activeDetail : -1,
zo: null,
init: function() {
zoom.nextTimer = setInterval(zoom.nextLoop, 5000);
},
nextLoop: function() {
console.log("zoom.nextLoop");
}
}
$(document).on('click', function(e){
console.log("klick");
zoom.init();
});
and expected that the zoom.nextTimer will be overwritten. But it seems to be wrong, a new timer is added.
How can I overwrite it?
Please see also http://jsfiddle.net/9FXu6/
intervalID is a unique interval ID you can pass to clearInterval().
— https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
The return value of setInterval is just a number that identifies the interval. You need to call clearInterval and pass it as the argument if you want to stop the interval from running the function again.
var nextTimer = setInterval(func, time);
clearInterval(nextTimer);
You need to call clearInterval(<reference to the timer>) to make sure it won't get executed again.
You might also have more luck with setTimout which only gets called once.

JavaScript: window.setTimeout(), force early expire

I have a <div> on my page that refreshes automatically every two minutes with updated log entries. When I first load my webpage, I call the following function.
function getLogs() {
var filter = $('#filter').val();
$.get("index-ajax.asp", { queryType: "getLogs", filter: filter,
uTime: new Date().getTime() },
function(data){
$("#logEntries").html(data);
window.setTimeout("getLogs()",120000);
});
}
I know the above code could be cleaner with window.setInterval(...); but I just like the control of window.setTimeout(...);.
My question, is it possible to cancel the next timeout execution? In the event that I change the filter, I'd like to cancel the next timeout, and call the function right away, which would reschedule the timeout function. Is there a better way to achieve that result?
Note that the above code is in jQuery.
Yes, use clearTimeout.
Ex:
var clr = window.setTimeout(getLogs,120000);
The when you wan to clear it:
clearTimeout(clr);
setTimeout returns a timerID that you can pass to clearTimeout:
// Note we are passing the *function* rather than a string
// Also note the lack of () - we are *not* calling the function
// setTimeout will do that for us
var timerID = setTimeout(getLogs, 120000);
// Fake condition - we cancel the timer if the timerID is even
if (timerID % 2 === 0) {
clearTimeout(timerID);
}
You could always define a new variable based on a filter value and if that filter value is set, use a while statement to omit the timeout:
if(filter == "whatevs"){
var i=true;
}
function(data){
$("#logEntries").html(data);
while(i!=true){
window.setTimeout("getLogs()",120000);
}
}

Keypress with delay, how to limit to only one execution of function call?

I'm setting up a form to lookup or create a new city record in a web app. I need the text field for the city to do the following:
Upon receiving text input, show a "spinner" indicating the computer is processing the input.
After the user has stopped typing for 1 second, send an ajax request to check the input.
Respond with the status (whether the input is valid).
I have this almost working but I have one major issue: the delay script I wrote works but after the delay is over it runs the rest of the function once per keyup that occurred during the delay. I would like it to only run once. Here's the code I'm working with (the console log events would be replaced with other function calls later):
$(function() {
locationSelector.initialize();
});
var locationSelector = {
initialize: function() {
locationSelector.bindCityName $('input#city_name')
},
city: {
status: function( status ) {
console.log( "Status message: " + status );
},
error: function(message) {
console.log("Error message: " + message );
}
},
bindCityName: function(selector) {
selector.on('keyup', function() {
locationSelector.city.status('loading');
var timer = null;
if(timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout(
function() { locationSelector.getCity( selector ); },
1000
);
});
},
getCity: function(selector) {
if( selector.val() == "" ) {
locationSelector.city.error('Cannot be blank.');
} else {
console.log("AJAX REQUEST");
}
}
};
Why is the getCity function is being run once per keyup, and how can I fix that? Also, to be honest I'm very much a javascript novice, so I would appreciate any other suggestions on how to improve this code scaffold.
Thanks!
For starters, the variable declaration for timer needs to be in a scope that lasts from one key event to the next. As it is, it is a local variable that gets recreated from scratch on every key event so you're getting multiple timers going at once.
Move this:
var timer = null;
to the global scope or a higher scope that persists from one key event to the next. You can also define the timer variable as a property of location selector if you want:
var locationSelector = {
// other properties defined here
timer: null
}
Then, you can refer to it as locationSelector.timer. I'd also suggest that when your timer actually fires that you should set locationSelector.timer = null since a timer is no longer active.
It also looks like you'll need to clear the 'loading' status once you run the ajax.
And, your timer is set for 2 seconds, but you said you want to wait 1 second for no typing.
It looks like the problem is here:
var timer = null;
if(timer) {
window.clearTimeout(timer);
}
Timer gets set to null, so it never gets cleared. I'd suggest declaring timer at the top, above initialize, and then setting it to null only after you clear it, or after it gets executed.

Categories

Resources