Troubleshooting: Dealing with Stack Overflow Error when using setInterval in Vue Programming

I am facing a stack overflow error while creating a timer using Vue, and I'm struggling to understand the root cause. Can someone provide insights on the following code:

Here is my template structure:

<span class="coundown-number">  {{ minutesRemaining }} : {{ secondsRemaining }}</span>
<span v-if="countdownDone"&g DONE </span>
<button v-if="running" class="custom-button" type="button" @click="runCountdown(countdownTime)">Start</button>
<input class="set-time" type="number" v-model="countdownTime" placeholder="Enter a Time in Minutes">

This is the implementation in my JavaScript file:

export default {
  name: 'Countdown',
  props: {
  },
  data() {
    return {
      running: true,
      countdownTime: null,
      remainingTime: null,
      countdownDone: false,
    }
  },
  computed: {
    minutesRemaining() {
      return (this.remainingTime - (this.remainingTime % 60)) / 60;
    },
    secondsRemaining() {
      return this.remainingTime % 60;
    },

  },
  methods: {
    runCountdown(timerTime) {
      let currentTime = timerTime*60;
      this.remainingTime = currentTime;
      if (currentTime > 0){
        currentTime--;
        setInterval(this.runCountdown(this.currentTime), 1000);
      }
      else{
        this.countdownDone = true;
      }   
    }
  }
}

I suspect the issue lies with how I'm calling the setInterval function within the same method it's being created. However, I'm unsure of an alternative approach for initialization.

If it were defined externally as

let tick = setInterval(runCountdown, 1000)
, how can I trigger it onclick? Any guidance on resolving this issue and understanding the underlying concept would be greatly appreciated.

Answer №1

Yes, the issue lies here:

runCountdown(timerTime) {
  let currentTime = timerTime*60;
  this.remainingTime = currentTime;
  if (currentTime > 0){
    currentTime--;
    setInterval(this.runCountdown(this.currentTime), 1000); // This specific line
  }
  else{
    this.countdownDone = true;
  }   
}

You're not passing the function as a callback, instead, you're calling it immediately and indefinitely.

The correct approach is to invoke it within a callback in the setInterval method.

setInterval(() => { this.runCountdown(this.currentTime) }, 1000);

Although setInterval will repeatedly call this function at exponential intervals, you might consider utilizing setTimeout for your needs.

setTimeout(() => { this.runCountdown(this.currentTime) }, 1000);

Answer №2

Although Phiter's response did touch on the main question I posed, it unfortunately falls short due to a critical logic flaw in the code.

Let me address the error in my thought process:

methods: {
    runCountdown(timerTime) {
      let currentTime = timerTime*60;
      this.remainingTime = currentTime;
      if (currentTime > 0){
        currentTime--;
        setInterval(this.runCountdown(this.currentTime), 1000);
      }
      else{
        this.countdownDone = true;
      }   
    }

The problem lies in the fact that runCountdown was initially accepting time in minutes and then converting it to seconds within the function itself.

This resulted in a cycle where each callback to runCountdown from setInterval would mistakenly multiply the time by 60 again, leading to an infinite loop of multiplication and subtraction.

To resolve this issue, I introduced a computed property called countdownInSeconds to properly convert the user's input from minutes to seconds, which is then passed as the parameter to runCountdown.

Here's the revised code snippet:

<template>
  <div class="countdown">
    <h1>How long would you like to study for?</h1>
      <span class="countdown-number">  
        {{ minutesRemaining }} : {{ secondsRemaining }}</span>
        <span v-if="countdownDone">DONE</span>
      <button v-if="running" class="custom-button" type="button" 
            @click="runCountdown(countdownInSeconds)">
         Start
      </button>
    <input class="set-time" type="number" v-model="countdownTime" 
      placeholder="Enter a Time in Minutes"> 
  </div>
</template>

<script>

export default {
  name: 'Countdown',
  props: {
  },
  data() {
    return {
      running: true,
      countdownTime: null,
      remainingTime: null,
      countdownDone: false,
    }
  },
  computed: {
    countdownInSeconds(){
      return this.countdownTime * 60;
    },
    minutesRemaining() {
      return (this.remainingTime - (this.remainingTime % 60)) / 60;
    },
    secondsRemaining() {
      return this.remainingTime % 60;
    },

  },
  methods: {
    runCountdown(timerTime) {
      // assign the remainingTime to the current seconds to allow for allow for computed properties to access this loop
      this.remainingTime = timerTime;
      // if the timer time is still above 0, keep running the loop; will also need to check to see if time has been
      // paused, reset or changed
      if (timerTime > 0){
        timerTime--;
        setTimeout(() => {this.runCountdown(timerTime)}, 1000);
      }
      else{
        this.countdownDone = true;
      }   
    }
  }
}
</script>

I hope this explanation clarifies the issue at hand!

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

JavaScript special character encoding techniques

I'm trying to create a function to remove special characters in my JavaScript code. However, whenever I try using chr(46), it throws a syntax error. Does anyone have any suggestions on how I can successfully implement chr(46) in my JS code? storageV ...

Creating a dynamic JSON array with a single key as an array

After converting data from an excel sheet into a json array, here is the structure: [{ 'booktitle': 'Leading', 'bookid': '56353', 'bookauthor': 'Sir Alex Ferguson' }, { 'booktitle&ap ...

What steps can I take to prevent receiving a 400 (Bad Request) error when using ajax PUT

Having an issue with sending data using JavaScript and AJAX. The objective is to send the data via PUT method to the server. var payload = 'id=' + id + '&brand=' + brand + '&model=' + model + '&country=' ...

Is there a more efficient approach to streamline Javascript code similar to the chaining method used in JQuery?

When working with jQuery, it's possible to streamline the code by running multiple methods in a single statement: $("#p1").css("color", "red").html("Hello world!").attr("class","democlass"); But how can this be accomplished in Javascript? document. ...

Exploring a JSON file to generate a customized array for implementing autocomplete functionality in jQuery

I'm currently working on developing an autocomplete feature for a search bar that will display names of places in Norway. The data is being fetched from a REST API URL provided by a third party. As an example, when the input is "st" there are two res ...

Converting Plain JSON Objects into a Hierarchical Folder Structure using Logic

Looking at the data provided below: [ {name: 'SubFolder1', parent: 'Folder1'}, {name: 'SubFolder2', parent: 'SubFolder1'}, {name: 'SubFolder3', parent: 'SubFolder2'}, {name: 'Document ...

Locate a specific data point within an array of JSON objects

After receiving an array of JSON objects from JSP, I now have a set of data that contains book titles. "Titles":[ { "Book3" : "BULLETIN 3" } , { "Book1" : "BULLETIN 1" } , { "Book2" : "B ...

Error encountered while installing Material UI in Next.js with TypeScript and pure JavaScript configurations

I'm brand new to React and Next.js, so please forgive me for asking what may seem like a silly question. I'm attempting to install Material UI in a fresh Next.js application that I created using "npx create-next-app@latest". I've been refere ...

What is the best approach to managing deletions in Vue Apollo when dealing with intricate, nested queries?

I am facing a situation where I have a complex query that fetches multiple nested objects to populate a detailed screen with information. Now, my goal is to remove one of the deeply-nested objects and reflect this change on the screen without having to re- ...

Unveiling the mysteries of JSONP in conjunction with AJAX

JSONP allows for bypassing the same origin policy in JavaScript by using <script> tags to load third party data. However, I am uncertain about how JSONP is utilized together with AJAX. My assumption is that: When an AJAX call is initiated, a <sc ...

Ensure that dynamic functions are accurately typed within a proxy utilizing TypeScript

I am currently working on a unique function that utilizes a Proxy with a get trap to extract functions from multiple objects. The challenge I am facing is getting TypeScript to recognize these functions at compile time so that I can add them to my interfac ...

NextJS displays outcomes as per query parameters obtained from an external API

I have set up my NextJS app to connect to a rest API. The API returns results based on different filters in the query string, such as: /jobs /jobs?filter=completed /jobs?filter=upcoming /jobs?filter=cancelled On my NextJS page, I have a few buttons that I ...

When my route in NextJS processes the request, it returns a ReadableStream from req

I am encountering an issue with my code and I have tried looking for solutions in other similar questions without any success. Is there anyone who can assist me? Here is the content of my route.js file: import dbConnect from "@/lib/dbConnect"; i ...

Utilizing Typeahead for Autocomplete in Durandal: A Step-by-Step Guide

I am attempting to implement an autocomplete input field with typeahead (Twitter Bootstrap) in a modal, but I am encountering difficulties making it function properly. Additionally, this autocomplete field needs to be observable with Knockout so that selec ...

Tips for solving issues with dependencies in React applications

After running "npm install," I encountered the following errors in the console: elena@elena-dev:~/PROYECTO FINAL CTD/grupo-12/frontend/proyecto-integrador$ npm install npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While reso ...

Load elements beforehand without displaying them using a div

In order to efficiently manipulate my Elements using jQuery and other methods, I am exploring the idea of preloading them all first. One approach I have considered is creating a div with CSS display set to none, and placing all the elements I need for my w ...

Is there a way to substitute the function variable using JavaScript?

Is there a method to dynamically replace the variable 'abc' with 'cde' in HTML using JavaScript? For example, if I have the following code: <table width="150" border="0" cellspacing="0" cellpadding="2" id="productBox"> <tr> ...

Is there a way to disable auto rotation on a website when accessed from a mobile phone?

My current solution involves the following code: @media (max-height: 480px) and (min-width: 480px) and (max-width: 600px) { html{ -webkit-transform: rotate(-90deg); -moz-transform: rotate(-90deg); -ms-transform: rotate(- ...

Inserting an item into ng-model within a dropdown menu

I have a select box populated with data from my backend. This data is an array of objects: [Object { superkund_id="4", nod_id="12068", namn="Växjö Fagrabäck"}, Object { superkund_id="5", nod_id="9548", namn="Halmstad Bågen / Pilen"}] I am using ng-o ...

Verify the placement within the text box

Are there methods available in JavaScript or any JavaScript framework to determine the position within a textbox? For example, being able to identify that figure 1 is at position 2 and figure 3 is at position 3. Figure 1 Figure 2 ...