How to stop a function when it's called? - javascript

I'm building a program that either counts down or up and I've got it working however I like to press count-up in the middle of count down or vice versa and I like the counter to stop and count up or vice versa. how do I achieve that? thanks a lot for your help :)
function myFunctionUp() {
var Timer = setInterval(function () {
i++;
document.getElementById("mydata").textContent = i;
if (i >= 21)
clearInterval(Timer);
if (i == 21){
document.getElementById("mydata").textContent = "Boom-up!";
}
}, 1000);
}
function myFunctionDown() {
var Timer = setInterval(function () {
i--;
document.getElementById("mydata").textContent = i;
if (i <= 0)
clearInterval(Timer);
if (i == 0){
document.getElementById("mydata").textContent = "Boom-down";
}
}, 1000);
}

Use a variable to keep track of the way to count. When a button is clicked, invert the value of the variable :
let countDown = 10;
let increment = -1;
function count() {
countDown += increment;
document.getElementById('container').innerText = countDown;
setTimeout(() => count(), 1000);
}
document.getElementById('btn').addEventListener('click', function () {
increment = -increment;
});
count();
Working stackblitz here
You typically never "take control" on the execution of another method. When you want to do that, the logic must be inverted. The function itself must ask if it should continue.
With an example : let's take a function which works in an infinite loop, that you want to be able to stop on demand. In some languages, you could run some code in a thread and interrupt the thread on demand. But even if it is possible, it is generally a bad idea to stop some code at the middle of its execution.
A better way of doing that is to create a "should Continue ?" piece of code at the end of the iteration. It could read a variable or call a method etc. When you want to stop the iteration, you just have to set this variable and you know that the infinite loop will stop graciously at the end of the current iteration

Related

Counter not displaying each number, just shows final total

Why is it that the counter only shows final number vs seeing each number 1 by 1.
What needs to be done to accomplish this?
var counter = 100;
function countdown() {
while(counter < 1000) {
counter++;
console.log(counter);
document.getElementById('cc').innerHTML = counter;
}
}
countdown();
setInterval(countdown, 1000);
This problem is happening because the Javascript execution and page rendering are actually occurring in the same execution thread. This means that while the code is executing the browser will not be redrawing the page because running JavaScript blocks the updating of the DOM like in your example.
To solve this you can use the setTimeout() which allows you to specify a function that will be executed once after a set number of milliseconds. Now, there will be gaps in between the code execution in which the browser will get the chance to redraw the page. now, when you actually pass 0 as the the delay argument. it will schedule the callback to be run asynchronously, after the shortest possible delay - which will be around after JavaScript thread of execution is not busy (the callback function will be waiting in the callback queue to be pulled by the event loop to be handled after a really short time)
function count() {
var counter = 100;
var max = 1000;
function timeoutLoop() {
document.getElementById('cc').innerHTML = counter;
if (++counter < max){
setTimeout(timeoutLoop, 0);
}
}
setTimeout(timeoutLoop, 0);
}
count();
<div id="cc">
</div>
More about the event loop - https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
Great article about browser rendering - https://developpaper.com/the-process-of-browser-rendering-web-pages/
It's because you were using a while loop, instead use an if statement to check whether the counter has reached 1000. See below:
var counter = 100;
function countdown() {
if(counter < 1000) {
counter++;
console.log(counter);
document.getElementById('cc').innerHTML = counter;
}
}
countdown();
setInterval(countdown, 1000);
<div id="cc"></div>
You are not giving the browser time to breathe
Also why have a loop when setInterval loops?
And you want to count down. not up I guess
Also we want to stop the counting
Lastly we can save a bracket
let counter = 10; // 10 to show it works
let tId;
const cc = document.getElementById('cc');
function countdown() {
if (counter === 0) {
cc.innerHTML = "DONE!";
clearInterval(tId); // stop
return
}
// console.log(counter);
cc.innerHTML = counter;
counter--;
}
countdown();
tId = setInterval(countdown, 1000);
<span id="cc"></span>

How to stop executinf function after certain amount of time in JavaScript

function avoidAfterTime() {
var startTime = new Date().getTime();
var interval = setInterval(function () {
if (new Date().getTime() - startTime > 3000) {
clearInterval(interval);
console.log("more than 2 sec")
return;
}
longWorking();
}, 2000);
}
avoidAfterTime();
function longWorking(){
var t;
for (i = 0; i < 1e10; i++) t = i;
console.log(t);
}
Hello. I am very new to JS. But I need to stop running some function (here it is longWorking) which can be executed for few seconds or for so much time. And I want to abort the function in case of it takes too long. I guess I know how to make it using, for example, threads in some other programming language. But I have no idea about making it in JS. I thought in this way (above)... But it doesn't work. Can someone help me?
hmm, I drafted this example. So it's a function that runs every second and if it takes more than 6 seconds it will stop. So basically you can put your work load in the doSomething() function and let it work every second and stop it if it takes too long. Or you can stop it based on a value. It depends on what do you want to do with it. I used the module pattern to isolate the logic and the variables. So you can encapsulate your logic in a module like way.
(function() {
'use strict';
let timing = 0;
const interval = setInterval(doSomething, 1000);
function doSomething() {
timing++;
if (timing > 5) {
clearInterval(interval);
}
console.log('working');
}
})();
Is this something you are looking for?

How to get the value for one function to another?

I'm learning Javascript, I read about scope and variables but can't get information about how to send variables between the functions.
Please can someone to explain how to be with this situation and it would be great to recommend something to read about it.
I want to draw a picture 30 times with 30 different parameters, and get the last parameter for checking function:
function loadImg{
.....
img.onload = function() { // Loading first picture at the start
........
boo.onclick = function() { // the function which by click start all process
var i = 0;
var num; // the variable which I'm going to use for random numbers.
setInterval(function() {
// here I'm generating random numbers
num = Math.floor(Math.random() * imgs.length);
// and then start draw() function, which is going to get the 'num' parameter and draw a pictures with time interval ONLY 30 times
if(i < 30){
draw(num);
i++; }, 2000);
check(num); // after all, I want to run "check()" function which is going to get THE LAST from that 30 generated 'num' parameter and check some information. But is undefined, because it's outside the setInterval function and I don't wont to put it in, because it will starts again and again.
How to get the last parameter for check(num) function?
P.S. Sorry for my english I've been trying to describe as good a as I can.
You could call check(num) inside the setInterval() function with a condition:
if(i < 30){
draw(num);
i++;
}
else
{
check(num);
}
You should also then end your loop as this will keep running indefinitely.
To do this assign the interval to a variable:
var myInterval = setInterval(function() {
And then clear the interval before calling check():
if(i < 30){
draw(num);
i++;
}
else
{
clearInterval(myInterval);
check(num);
}

SetInterval keeps setting when changing pages

So, I have a JavaScript issue that is probably as old as time, but I can't seem to figure it out. I have a form that takes up the whole page and has next and back buttons so the user can travel back and forth through the questions. (Single page app, no full refresh. If there was this would be easy!)
One of the requirements is to have a timeout function. So after they are idle after a cretin amount of time it logs them out to protect their information. The issue is that my interval keeps adding a new one every time I flip back and forth new pages. Thus creating multiple timers and insanity.
My code kind of looks like this.
var idle = 0;
var idleIntervalTimer = setInterval(timerIncrement, 1000); //This is what keeps being called
var counter = 0;
var timeout = 30;
var count = 20;
var resetCount = 20;
document.onmousemove = function() {
if(app.timer.get('available') === 'Yes'){ //I'm just using this to make sure that they have not already been logged out
count = resetCount;
idle = 0;
app.warning.close();
}
};
function timerIncrement() {
if(app.timer.get('available') === 'Yes'){
console.log(idle);
idle = idle + 1;
if (idle > 19 && count >= 0) {
count = count;
app.warning.show({ //This is just a warning message that shows up at the top of the page counting down before the app closes.
message: 'Logging out in <span class="warn">' + count + '</span> seconds.'
});
if(count != null || count >= 0){
count=count-1;
if (count === 0 && count != 'null'){
resetTimer();
app.workflow.resetWorkflow();
}
}
}
}
}
function resetTimer(){
count = resetCount;
idle = 0;
clearInterval(counter);
clearInterval(idleIntervalTimer);
app.warning.close();
}
I have tried a few different things. One being that I would set a blank variable at the top and use that blank variable to set the interval, but that didn't seem to work. I have also tried to detect if the interval was still active, but I don't really want to clear the interval, just not create another. Some help would be apprenticed very much!
I'm assuming that code gets called on every page flip. Don't set the interval timer immediately. You should create a function that will first clear it and then set.
For example do this instead:
var idleIntervalTimer;
function initIdleIntervalTimer(){
clearInterval(idleIntervalTimer);
idleIntervalTimer = setInterval(timerIncrement, 1000);
}
initIdleIntervalTimer();
Or try switching it the timer to the global scope, get rid of var idleIntervalTimer and do this:
clearInterval(window.idleIntervalTimer);
window.idleIntervalTimer = setInterval(timerIncrement, 1000);
It's a little ugly, but
window.clearInterval(localStorage['idleInterval'])
var idleIntervalTimer = setInterval(timerIncrement, 1000); //This is what keeps being called
window.localStorage['idleInterval'] = idleIntervalTimer;
EDIT: If you dont want to clear, wrap the entire init in a flag, eg
if (!window._intervalInitOccured){
window._intervalInitOccured = true;
//continue init

Why isn't clearInterval working in this code?

There is a function which sets an interval using setInterval(), but even after calling clearInterval(), I can see in the console that the else condition is still running. How can I clear that interval properly?
function increase(old, step, neu) {
var i = 0;
var delay2;
function countUp() {
if (i < 5) {
old += step;
// console.log("increase")
$("#total-price-value").text(old + " dollors");
$("#total-price-value").digits();
i++;
delay2 = setInterval(countUp, 80);
} else {
clearInterval(delay2);
console.log(delay2);
}
}
countUp();
}​
It looks like you're a little confused about the difference between timeouts and intervals. Timeouts fire only once; intervals fire many times. If you're using an interval, you probably only want to set it once (you're setting it every time). If you're using a timeout, you probably want to set it every time (like you're doing).
In order to fix the problem, you'll either want to switch to timeouts (probably the easiest; just a search/replace) or only set the interval once.
For example, here is how one might use setTimeout to count up to five:
var count = 0;
function timeoutFired() {
count++;
if(count < 5) {
setTimeout(timeoutFired, 1000);
}
}
setTimeout(timeoutFired, 1000);
Using timeouts, we don't need to clear to stop it from counting; simply not setting a timeout will prevent it from running again.
Here is how one might use setInterval:
var count = 0;
function intervalFired() {
count++;
if(count >= 5) {
clearInterval(interval);
}
}
var interval = setInterval(intervalFired, 1000);
If you want some code running periodically using intervals to stop, you must call clearInterval. Note that we only call setInterval once, versus setTimeout every time we didn't want it to continue.
Apparently, you have mistaken setInterval for setTimeout. setInterval runs the enclosed function every n milliseconds while setTimeout executes only once after n milliseconds.
I suppose you wanted to "tick until 5" so here's a sample:
function increase(old, step, neu) {
var i = 0;
interval = setInterval(function() {
if (i < 5) {
//do something at this "tick"
console.log(i);
i++;
} else {
//else, stop
clearInterval(interval);
}
},80);
}
increase();

Categories