Using Async/Await for Timers within a Loop in Javascript

Currently developing a "Timeblocks" style application for university. The main concept involves having a list of subtasks, each with a specified time limit. The goal is to iterate through these tasks, utilizing a timer to countdown the allocated time and then moving on to the next task. For example:

var todos = [
  { id: 1, task: "Finance", time: 1 },
  { id: 2, task: "Distribution", time: 1 },
  { id: 3, task: "Blah", time: 1 }
];

The above tasks would be iterated through, with a 1-minute countdown displayed in the console.

While I have successfully coded the core functionality, the countdown is not working correctly after the initial iteration. It seems to be counting down twice per second and then never stopping, eventually going into negative time. The interval should clear each time the timer reaches 0 and then restart when the next iteration begins.

Any assistance would be greatly appreciated.

P.S. I am also aware that the first iteration takes 1 minute to start, and I plan to address this issue as well!

Check out the code on StackBlitz here.

Answer №1

Avoid using global variables whenever possible. It's better practice to pass parameters/values as arguments to functions. Also, consider using 'let' and 'const' instead of 'var' for variable declarations!

// Import stylesheets
import "./style.css";

// Your Javascript code goes here!

const startBtn = document.getElementById("start");
startBtn.addEventListener("click", startHandler);

const tasks = [
  { id: 1, name: "Finance", time: 0.1 },
  { id: 2, name: "Distribution", time: 0.2 },
  { id: 3, name: "Blah", time: 0.2 }
];

let countdownInterval;
let secondsLeft;

function countDownTimer(task, resolve) {
  const minutes = Math.floor(secondsLeft / 60);
  let seconds = secondsLeft - minutes * 60;

  if (seconds < 10) {
    seconds = "0" + seconds;
  }

  const message = minutes.toString() + ":" + seconds;

  console.log(message);

  if (secondsLeft === 0) {
    alert("Timer done for task: " + task);
    clearInterval(countdownInterval);
    return resolve();
  }
  secondsLeft--;
}

function executeTimer(duration, task) {
  return new Promise(resolve => {
    secondsLeft = duration;
    countdownInterval = setInterval(countDownTimer, 1000, task, resolve);
  });
}

async function startHandler() {
  for (let i = 0; i < tasks.length; i++) {
    const timeForTask = tasks[i].time;
    const taskName = tasks[i].name;

    console.log("Starting timer for task:", taskName);
    await executeTimer(timeForTask * 60, taskName);
    console.log(taskName, "timer completed");
  }
}

Answer №2

Here's a modified version with a 5-second timer for a more efficient demonstration:

const tasks = [{
    id: 1,
    task: "Financial Planning",
    time: 1
  }, {
    id: 2,
    task: "Logistics",
    time: 1
  }, {
    id: 3,
    task: "Etc",
    time: 1
  }
];

const taskDuration = 5; // Timer set to 5 seconds

async function initiateHandler() {
  for (const task of tasks) {
    console.log('Current task', task.task);
    await countdown(task.time * taskDuration);
  }
}


initiateHandler();

function countdown(time) {
  function ticking() {
    const minutes = Math.floor(time / 60);
    let seconds = time - minutes * 60;

    if (seconds < 10) {
      seconds = "0" + seconds;
    }

    const message = minutes.toString() + ":" + seconds;

    console.log(message);

    time--;
  }
  const timerInterval = setInterval(ticking, 1000);
  return promiseSetTimeout(() => clearInterval(timerInterval), time * 1000);
}

// Utility function to execute a function after a delay and return a Promise
function promiseSetTimeout(func, time) {
  return new Promise(resolve => setTimeout(() => [func, resolve].forEach(x => x.call()), 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

Is it possible to detect inline elements that have been wrapped?

I am facing a challenge with displaying an indefinite amount of in-line elements. Depending on the width of the browser, some elements may shift to a new line. I am curious to know if it is possible to identify and isolate these rows of elements, or if the ...

Discover the procedure for extracting a dynamic value from JavaScript to PHP

Could the centerId value be utilized and transferred to a php variable? const data = { action: 'ft-add-member', maritalStatus: $('.ft-entry-relationship-info .ft-marital-status ul li.current a').data('dropdown' ...

Float two DIVs horizontally with the same height using jQuery

Having a strange issue with the website I'm currently working on and can't seem to figure out what's causing it. Something is definitely off with my javascript, but I just can't pinpoint the exact problem. Here's the situation: I ...

Encountering a syntax error with the AngularJS ng-class expression

While navigating through a tutorial application designed for use with the Ionic platform, which is based on angular 1.2.4, I encountered a perplexing error in this Angular markup: <content has-header="true" scroll="false"> <list> ...

Implementing a for loop within a scrolling function

How do I multiply functions inside the scroll loop? This is what I currently have: $(window).scroll(function() { b1Center = $("#block-1").offset().top - ($(window).height() - divHeight) / 2; b1Bottom = $("#block-1").offset().top - $(window).height(); b1T ...

Passing parameters from a parent component to a child component and then back to the parent component

I have a unique custom component called InputWithButton that has a distinct structure: const InputWithButton = ({ type = "text", id, label, isOptional, name, placeholder = "", value = "", showPasswordReset, error, isDisabled, buttonLabel, handleChange ...

Reposition the element at the bottom of its parent element

I am facing an issue with the HTML structure in my application: <div class="work-item"> <div class="image-container"> </div> <div class="text-container"> </div> </div ...

ES6: utilizing properties and methods of a subclass that inherit from the superclass

While ES6 does not have abstract methods or properties, is it possible to access some methods or properties from the parent class in an inherited class? class ParentClass { constructor(){ ParentClass.checkChildPropertyAccessibility(); Pa ...

Are you looking to convert this JSON using underscore or any other JavaScript utility tool?

Looking at this JSON data: [{"target": "mydata.12.2", "datapoints": [[763.7, 1368821100], [762.1, 1368821160], [223.11, 1368821220], [886.54, 1368821280], [112.3, 1368821340]]}] I need to strip the first key and square brackets so it appears like this: ...

Having difficulty with Angular's ng-options feature in a Select element

I'm currently tackling an issue with using ng-options to iterate through an array of objects and display specific properties in a select element. Upon querying the api/admin endpoint, I receive JSON data containing details of all users holding the ad ...

The passport authentication process is currently stalled and failing to provide any results

The current authentication process is functioning properly app.post('/login', passport.authenticate('local-login', { successRedirect: '/home', failureRedirect: '/login', failureFlash: true }) ); Howev ...

Instructions on accessing the subsequent li a starting from a designated location

My goal is to change the link color of the button with the id #idIMMUNOLOGY_9, which has the class .active_default, but I must start from the element with the id #idTERRITORIAL_8. I attempted this approach : $('#idTERRITORIAL_8').parent().find( ...

The android webview is having trouble loading HTML that includes javascript

I have been attempting to showcase a webpage containing HTML and JavaScript in an android webview using the code below. Unfortunately, it doesn't seem to be functioning properly. Can someone provide assistance? Here is the code snippet: public class ...

Tips for running Typescript files on a server in the background

I am currently working on a NodeJS application that consists solely of TypeScript files, without any JavaScript files. I'd like to run it on my server in the background. Any suggestions on how I can achieve this? I experimented with using the npm pa ...

What steps can be taken to enable users to draw a path on a Google Map?

I'm working on a new project for a Facebook app that will allow users to map out their marathon route using Google Maps. I plan to utilize mySQL database records to store fixed points along the path (such as specific locations based on latitude and lo ...

The variable is constantly reverting back to its initial value

Here is the code snippet: function send() { var nop = 6; var send_this = { nop: nop }; $.ajax({ type: "GET", data: send_this, url: "example.com", success: function(r) { ...

javascript how to trigger a change or input event when handling a paste event

I have successfully overridden the paste event on the document object, but now I want to trigger the onchange, oninput, and other input events in the event handler for the paste event. document.addEventListener('paste', function (e) { ...

Encountering an issue in Typescript where utilizing ref in ShaderMaterial triggers an error stating: "The anticipated type is originating from the property 'ref' declared within the 'PolygonMat' type definition."

While working on a shaderMaterial with the drei library, I encountered an issue with TypeScript when using ref: Type 'RefObject<PolygonMat>' is not assignable to type 'Ref<ShaderMaterial> | undefined'. I defined the type ...

Prevent the automatic inflation of bubbles on the D3 World Map

Currently, I am developing a D3 world map with a zoom feature that allows users to zoom in up to the boundary level of any country or county by clicking on it. I have successfully added bubbles that point to various counties in Kenya, and these bubbles en ...

Check if the element with the ID "products" exists on the page using JQuery. If it does, then execute a certain action

Is there a way to create a conditional statement that executes if the element with the ID "products" is present in the HTML code? Thanks in advance for your help! Pseudo code using JavaScript (JQuery) if ( $('#products').length ) { // do s ...