Endless cycle within the while loop without any obvious cause

I've been tinkering with a timer and thanks to some feedback I received in this community, everything is running smoothly. Here's what the current version looks like for reference:

https://i.stack.imgur.com/Qd7ll.png

Here's a snippet of my code (please keep in mind that it's a work in progress and some functionalities are not fully implemented yet; any function containing alert("workin"); is still under development.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>

<html>

<head>

<title>WIP</title>
<meta charset="UFT-8">
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>


<script>

$(document).ready(function() {
timerSet(9,12);
timerRun();
});

function timerReset() {
alert("workin");
}

function timerSet(inputMinutes, inputSeconds) {
minutes = inputMinutes;
seconds = inputSeconds;
finalTimeInSeconds = minutes*60 + seconds; //finalTimeInSeconds stores the time required to reach 00:00 on the timer in seconds.
timerPrint();
}

function timerAdd(inputMinutes, inputSeconds) {
alert("workin");
}

function timerSubtract(inputMinutes, inputSeconds) {
setTimeout(function () {
if(minutes > 0 && seconds == 0) {
minutes--;
seconds = 59;
} else {
seconds--;
}
timerPrint();
}, 1000);
}

function timerRun() {
timerSubtract();
}

function timerStop() {
alert("workin");
}

function timerPrint() {
displayMinutes = (minutes.toString().length == 2) ? minutes : "0" + minutes;//ternary operator: adds a zero at the beginning 
displaySeconds = (seconds.toString().length == 2) ? seconds : "0" + seconds;//if the number has only one character.
$("#timerText").text(displayMinutes + ":" + displaySeconds);
}

function totalTime() {
var totalTimeInSeconds = minutes*60 + seconds;

return totalTimeInSeconds; //totalTimeInSeconds represents the time displayed on the timer in seconds.
}

</script>

</head>

<body>

<div id="timerText">00:00</div>

</body>

</html>

Now here's the issue I'm facing: In the timerRun() function, I aim for the timerSubtract() function to loop as long as totalTime() > 0, but when I use a while loop, the page crashes. Why does this happen? I don't believe it's an infinite loop. Any suggestions on how I can achieve the desired functionality?

Appreciate any help or insights provided! :-)

Answer №1

The issue lies in the fact that timerSubtract accomplishes its task using setTimeout.

When you utilize setTimeout, it essentially queues up the function to be executed later. Then, when the program is idle (and enough time has passed), it executes the next queued function. By implementing a while loop, you are preventing the runtime from executing these functions scheduled with setTimeout.

One approach to rectifying this while still making use of setTimeout would be something like:

function timerRun() {
    if (minutes > 0 && seconds == 0) {
        minutes--;
        seconds = 59;
    } else {
        seconds--;
    }
    timerPrint();
    // Set up timerRun to execute again in 1 second
    setTimeout(timerRun, 1000);
}
timerRun();

Answer №2

Have you considered using setInterval instead of setTimeout in your timer function?

Check out this example on jsfiddle

setInterval(function () {
    if(minutes > 0 && seconds == 0) {
        minutes--;
        seconds = 59;
    } else {
        seconds--;
    }
    displayTimer();
}, 1000);

If you want to learn how to stop the setInterval, check out this resource: How to Stop "setInterval"

Answer №3

The timerSubtract function is designed to initiate a timeout that will ultimately update the variables minutes and seconds. It does not directly modify these variables upon execution.

Running this function in a loop with the expectation of seeing immediate changes in the variables will not work as intended due to JavaScript's single-threaded nature. The browser needs to yield control back in order for timeout events to be processed. Otherwise, the loop will block the execution of timeouts.

If JavaScript supported multi-threading, the loop could potentially spawn numerous timeouts rapidly, causing unpredictable results. Instead, utilizing a single setInterval within timerSubtract ensures consistent countdown behavior:

function timerSubtract(inputMinutes, inputSeconds) {
    setInterval(function() {
        if (minutes > 0 && seconds == 0) {
            minutes--;
            seconds = 59;
        } else {
            seconds--;
        }
        timerPrint();
    }, 1000);
}

function timerRun() {
    timerSubtract();
}

Answer №4

Like Jonathan mentioned, utilizing setInterval is the way to go. To enhance his suggestion, I recommend incorporating clearInterval() function to halt the countdown at 0 (assuming that's your goal). Here's an improved version of the code:

function timerSubtract(inputMinutes, inputSeconds) {
    var countdown = setInterval(function () {
        if(minutes > 0 && seconds == 0) {
            minutes--;
            seconds = 59;
        } else {
            seconds--;
        }

        if( totalTime() <= 0){
            clearInterval(countdown);
            // The timer has ended, perform additional actions...
        }

        timerPrint();
    }, 1000);
}

Furthermore, it's worth noting that over time the timer may lose accuracy. For more precise timing, consider fetching the current system time when starting the timer, then upon each interval, retrieve the current time again and calculate the difference between the two values (current - start) to determine the actual elapsed time. Afterwards, deduct the elapsed time from the initial total to obtain the remaining time.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

jQuery fieldset.change is a feature that allows you to manipulate

I'm looking to update the value of a button when a radio button is clicked. <fieldset id="product-color"> <input type="radio" id="red" name="color" value="Red"> <label for="red">Red</label><br> <input typ ...

Sorting data by percentages in AngularJS

I am currently facing an issue with sorting percentages in a table column. Despite using methods like parseFloat and other AngularJS (1.5.0) sorting techniques, the percentages are not being sorted as expected. [ {percentage: 8.82} {percentage: 0. ...

Solving filtering issues within React using a combination of conditions

I've been struggling to selectively remove an item from my array. The current filter I'm using is removing too much. Here is the array in question: [ { "domain": "domain1.com", "slug": "moni ...

Display the Sencha Touch Picker with the previously selected option showing

When using the Sencha Touch Picker component, I noticed that if I select a data and then hide the picker, upon showing it again, only the first record is selected each time. I want the picker to display my last selection when shown again. To achieve this ...

I am sending an AJAX request to a remote server in order to retrieve access records

Currently, I am attempting to retrieve data by sending an ajax request to a remote server controller from my current remote page. Below is the code for my first remote view page: <?php include 'header.php'; ?> <script src="/assets/js/ ...

Unable to fetch permissions for user:email via GitHub API

Currently, I am utilizing node-fetch to fetch an OAuth2 token from an OAuth2 GitHub App. The obtained token allows me to successfully retrieve user information from "https://api.github.com/user". However, I also require the email address, which necessitate ...

MongoDB Client > Error: No operations provided - cannot proceed

NPM Library: "mongodb": "3.1.4" Encountering an issue while attempting to bulk insert a list of data: Here is the code snippet: db.collection('products').insertManyAsync(products, {ordered: false}) The error message displayed: An Invalid O ...

The user's input is not being accurately represented when making an AJAX request to the

When attempting to incorporate a user's city input (e.g. Los Angeles) into Ajax URL parameters, there seems to be an issue where the '+' is not being added between "los angels", resulting in a broken URL when console.log(searchURL) is used. ...

What is causing the failure of success function commands to be executed?

Currently, I am facing some inconsistencies between my locally hosted app on WAMP (working perfectly) and the deployed version of my app. In an attempt to resolve this issue, I am working with CodeIgniter and jQuery AJAX. As part of my troubleshooting proc ...

Determine the number of input tags within a div element by utilizing the closest property in jQuery

Sorry for the silly question, but I've been struggling to find a solution. Spent hours scratching my head. Here is my HTML structure: <div class= 'container'> <div class="someclass"> <input>some content</in ...

Hiding the overflow conceals the entire image in one direction, while leaving the other exposed

Here is the code I have written for my project (view fiddle here): img { width: 200px; height: 200px; } .image-container { width: 600px; height: 200px; overflow: hidden; } I am working with multiple images, all sized at 200px by 200p ...

"Exploring the world of CSS3: Arrow shapes and animated effects

Looking at the image provided, my task is to create and animate it. I was considering using CSS3 border-radius instead of an actual image. Below are the HTML and CSS code that I have so far. The animation I envision involves the arrow gradually appearing ...

Enhance your mouse movement for optimal efficiency

I am looking to implement a feature on a webpage where a menu is displayed whenever the cursor is near the edge of a <div>. One way to achieve this is by using the .mousemove function to track the cursor position and show/hide the menu based on proxi ...

Can someone explain the distinction between 'return item' and 'return true' when it comes to JavaScript array methods?

Forgive me for any errors in my query, as I am not very experienced in asking questions. I have encountered the following two scenarios :- const comment = comments.find(function (comment) { if (comment.id === 823423) { return t ...

JSON nested error: Cannot read property 'length' of undefined

Having some trouble working with a nested array within a JSON in D3JS, specifically encountering a "property length undefined" error at the line: .attr("d", function(d) { return line(d.points); }). Below is the JSON data structure: [ { "aspectRatio" ...

Retrieving ng-model using ng-change in AngularJS

Here is an example of the HTML code I am currently working with: <select ng-model="country" ng-options="c.name for c in countries" ng-change="filterByCountry"></select> This HTML snippet is being populated by the following object containing a ...

The button I have controls two spans with distinct identifiers

When I press the player 1 button, it changes the score for both players. I also attempted to target p2display with querySelector("#p2Display"), but it seems to be recognized as a nodeList rather than an element. var p1button = document.querySelector("# ...

Create a list using ng-repeat in AngularJS, each item separated by "custom categories"

I am looking to create a dynamic list that will display values entered by users, categorized by custom categories. The challenge is that I do not know in advance which category each element will belong to. Here's an example of how I envision the list ...

Is there a way to manipulate the placement of an image within a div using CSS?

Teaching myself HTML has been quite the journey. Right now, I'm in the process of building a website purely for its aesthetic appeal, and I seem to be hitting a roadblock with the CSS/div element. As of now, it appears like this. When the h1 is remove ...

Can you explain the distinctions among “assert”, “expect”, and “should” in the Chai framework?

Can you explain the variations between assert, expect, and should? How do you know when to utilize each one? assert.equal(3, '3', '== turns values into strings'); var foo = 'bar'; expect(foo).to.equal('bar' ...