Stop a setTimeout function in AngularJS (hint: use $timeout) - javascript

I'm making a quiz-type app in which, when user gets a question, a timer of 10 seconds goes like this:
$scope.timer2 = function() {
setTimeout(function() {
console.log('times up!!!!');
}, 10000)
}
and it is being called when a question arrives like this:
timerHandle = setTimeout($scope.timer2());
And after this timer2 execution another question pops up and so on, another way of a question being popped up is that the user selects an option also then a new question comes up. So far so good but the problem is that if suppose 5 seconds were passed and then user selects an option, the "timer2" still shows "times up!!" after 5 more seconds and another timer for the new question also shows "times up!!" if the user hasn't selected any option.
What I'm trying to say is that I want the timer2 to stop when user selects any option, and then i want again this timer to be called as a new question will arrive.
This is the angular code which executes when user selects an option:-
$scope.checkanswer=function(optionchoosed){
$http.get('/quiz/checkanswer?optionchoosed='+ optionchoosed).then(function(res){
if(res.data=="correct"){
$scope.flag1=true;
$scope.flag2=false;
}else{
$scope.flag2=true;
$scope.flag1=false;
}
$http.get('/quiz/getquestions').then(function(res){
console.log("respo");
$scope.questions=res.data;
clearTimeout($scope.timerHandle); //not working
timerHandle = setTimeout($scope.timer2());

You can try using the service of AngularJS $timeout.
Then do something along these lines:
var myTimer = $timeout(function(){
console.log("hello world")
}, 5000);
....
$timeout.cancel(myTimer);

Take a look at the MDN documentation for setTimeout.
As you can see, that function returns a unique identifier.
At this point, you can call clearTimeout passing that UID as parameter:
let myTimeout = setTimeout(myFunction, millis); //Start a timeout for function myFunction with millis delay.
clearTimeout(myTimeout); //Cancel the timeout before the function myFunction is called.

Since you do not provide working example let me do the best guess. Your function does not return handle from inner setTimeout so it cannot be cancelled. What about such modifications:
$scope.timer2 = function() {
return setTimeout(function() { // added return statement
console.log('times up!!!!');
}, 10000)
}
and then
timerHandle = $scope.timer2(); // simply call timer2 that returns handle to inner setTimeout

Related

How to make functions get called sequentially in JS? [duplicate]

This question already has answers here:
Wait until setInterval() is done
(6 answers)
Closed 2 years ago.
I am making a webpage where once the user clicks on the start button, some changes will happen to the CSS of the page (I wrote the required JavaScript (JS) code). Only after these changes happen, I want some other changes to happen. In an attempt to achieve this, I wrote calls to 2 functions inside the function that gets called once the event happens: (In the below JS code, the 2 functions begin called inside the function that which gets triggered by the "click" event are- startCountdown and showWords)
document.getElementById("startButton").addEventListener("click",startTheGame);
function startTheGame()
{
var contentSlides = document.getElementsByClassName("slide");
// Game started so we are hiding the start slide!
contentSlides[0].classList.add("hideDisplay");
//
// Now the "321 Go!" down timer is to be shown!
contentSlides[1].classList.remove("hideDisplay");
startCountdown(document.getElementById("onClickCount"));
showWords();
//
}
function startCountdown(reqElement)
{
var time = 2;
var intervalId = setInterval(function ()
{
reqElement.innerText = time;
if(time==="Go!")
clearInterval(intervalId);
time-=1;
if(time===0)
time = "Go!";
},1000);
}
function showWords()
{
alert("Hi!");
}
In the showWords function also, I wish to make some changes to the page. But, I want it to get executed only after the startCountdown function gets executed completely. As of now when I am running the above code, as soon as I click on the button, the alert is popping up! - But I don't want it to happen.
What changes do I need to make?
(After the showWords function gets executed completely - I want one more function to be executed - in this way I want the functions to be executed sequentially - i.e. the changes must happen in a specific order.)
Thanks for the help!
P.S.: Please let me know if you aren't able to understand my question.
so when it's called clearInterval like this
document.getElementById("startButton").addEventListener("click",startTheGame);
function startTheGame()
{
var contentSlides = document.getElementsByClassName("slide");
// Game started so we are hiding the start slide!
contentSlides[0].classList.add("hideDisplay");
//
// Now the "321 Go!" down timer is to be shown!
contentSlides[1].classList.remove("hideDisplay");
startCountdown(document.getElementById("onClickCount")); //
}
function startCountdown(reqElement)
{
var time = 2;
var intervalId = setInterval(function ()
{
reqElement.innerText = time;
if(time === 0){
clearInterval(intervalId);
reqElement.innerText = "Go!"
showWords();
}
time--;
},1000);
}
function showWords()
{
alert("Hi!");
}

Javascript - call a function when you finish typing

Let's say I have an input in wich the user is going to type some text. When he finish typing I want to call a function automatically.
This is what I have done till now:
<input type="text" oninput="change();"/>
<script>
function changing(){
alert('You stoped typing!');
}
function change(){
clearTimeout(changing);
setTimeout(changing, 2000);
}
</script>
What I am expecting :
When you type, change is called. It cancels the last changing that was supposed to run in 2 seconds and run a new changing within 2 seconds.
What actually happens :
When you type, change is called. It doesn't cancel the last changing that was supposed to run in 2 seconds but still run a new changing within 2 seconds. As you type, the first alert window will appear 2 seccond after you start typing and keep showing again and again one after another.
Is there something wrong in my code?
setTimeout() returns a timer ID. It is that timer ID that you must pass to clearTimeout() for it to work properly (you are passing the callback function to clearTimeout() and that is not how it works).
So, you need to store the return value from setTimeout() into a variable in a lasting scope that you can then later pass to clearTimeout() like this:
<input type="text" oninput="change();"/>
<script>
function changing(){
alert('You stoped typing!');
}
var timer;
function change(){
clearTimeout(timer);
timer = setTimeout(changing, 2000);
}
</script>
The setTimeout() function returns a value that must be used later with clearTimeout() if you need to cancel it.
var timer;
function changing(){
alert('You stoped typing!');
}
function change(){
clearTimeout(timer);
timer = setTimeout(changing, 2000);
}

How can I reset a settimeout

I tried the answer here: Resetting a setTimeout, but it doesn't seem to be working for me.
I'm building a catalog viewer using Owl Carousel. I have a function set to go off on the afterMove event handler that shows what page the user is on. It displays the page counter and then sets a timeout to have it fadeout after 1 second. Probably is lots of people go through pages faster than once per second. So, I need to reset the timeout if the function gets called again.
function showCounter(){
var $counter = $('#counter');
//clear timeout
window.clearTimeout(timeout);
//Display counter
$counter.show();
//set timeout
var timeout = window.setTimeout(function(){
$counter.fadeOut(500);
}, 1000);
}
But window.clearTimeout(timeout) doesn't seem to be working and I'm not sure why
Thanks
var timeout inside the function makes timeout local to the function; thus, every time you call showCounter, timeout is undefined. Move the variable declaration out of the function:
var timeout;
function showCounter() {
// ...
timeout = // NO VAR! ...
// ...
}

Recursive Javascript Function For Online Status

I have the following javascript.
function isOnline() {
var status = navigator.onLine ? 'online' : 'offline',
indicator = document.getElementById('indicator'),
current = indicator.textContent;
// only update if it has change
if (current != status) {
// update DOM
indicator.textContent = status;
// trigger handler
handler[status]();
};
if(current == 'offline')
{
setInterval(checkServerStatus, 500)
checkServerStatus();
}
};
function checkServerStatus()
{
var img = document.createElement("img");
img.onload = function()
{
alert('yey!');
setInterval(isOnline, 500);
isOnline();
};
img.onerror = function()
{
alert('meh.')
};
img.src = "image-small.jpg"; //image on server(should be small so that intermittent checks are not bad)
}
$(checkServerStatus);
What I'd like to do is the following.
First call checkServerStatus() -- > if online run isOnline() every 500ms to keep checking the status of the website. In my isOnline code if I ever check that it is offline, then run checkServerStatus again, and if I'm still connected go back.
In addition, I'd like to add two things to this, when checkServerStatus fails, recursively call another function isOnline2 to check until it is online, where I then call checkServerStatus again.
The issue I am currently running into right now is that checkServerStatus keeps showing the 'yey' alert. I thought that, the function only starts once, and then using setInterval(isOnline, 500) will continue to run. After isOnline changes to offline, then I would run my checkServerStatus function again.
Any ideas on how to adjust this would be extremely appreciated.
Set your interval to a variable and then use clearInterval() when you want to stop your interval.
var interval = setInterval();
clearInterval(interval);
setInterval() runs a function on an interval endlessly, until cancelled with clearInterval().
In your case, I'd actually suggest not using setInterval but instead use setTimeout. This allows better control of execution: setTimeout runs once. At the completion of each function, you should be calling setTimeout to invoke either checkServerStatus or isOnline, as appropriate.
function isOnline() {
.....
if(current == 'offline') {
setTimeout(checkServerStatus, 500);
} else {
setTimeout(isOnline, 500);
}
};
It also prevents overlap: if, for example, checkServerStatus takes more than 500 ms to complete, with setInterval you'll be running it multiple times at the same time.

setInterval in javascript based on changes made

I'm having an issue with a javascript requirement. I have a html calling a script perpetually every 1500ms using setInterval.
var t = setInterval(loadData(),1500);
The loadData function calls a script which returns a JSON as a list, what I want to do is to change from a fixed interval to a variable interval. For instance, if there are no changes made between two calls to the script, I must set another value for the interval. I heard I could use jquery linq to compare the length of the list at the beginning and the list when refreshing to change the time value. I also heard I could save the value of count in a cookie to compare always.
Any idea please? I would be grateful. Thanks in advance.
I'm guessing you're trying to do:
var speed = 1500,
t = setInterval(loadData, speed);
function loadData() {
if (something == true) {
something = false;
speed = 3000;
clearInterval(t);
t = setInterval(loadData, speed);
}else{
//do something
}
}
You should just reference the function, adding the parenthesis runs the function immediately. When using a variable for the speed, you'll need to clear and run the interval function again to change the speed.
if the interval is variable, then you can't use setInterval, which period won't be changed after the first call. You can use setTimeout to alter the period:
var period=1500
var timer;
var callback = function() {
loadData();
timer = setTimeout( callback, period )
};
var changePeriod = function( newPeriod ) {
period = newPeriod;
}
//first call
callback();
now, you just need to call changePeriod( ms ) to change the period afterwards

Categories

Resources