简体   繁体   English

Javascript - 循环中的异步/等待计时器

[英]Javascript - Async/Await Timer in loop

I'm working on a "Timeblocks" type application (for uni).我正在开发“Timeblocks”类型的应用程序(用于 uni)。 The core idea being we have a list of subtasks, each with a designated time allowance.核心思想是我们有一个子任务列表,每个子任务都有指定的时间限制。 I want to be able to iterate through the tasks, use a timer to countdown the allocated time allowance then iterate 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 }
];

We would iterate through the above, counting down 1 minute each in the console.我们将遍历上述内容,在控制台中每个倒计时 1 分钟。

I have that core functionality coded, the iteration itself works with async/await.我已经对核心功能进行了编码,迭代本身与 async/await 一起工作。

stackblitz here:堆栈闪电战:

https://stackblitz.com/edit/js-87ykxt https://stackblitz.com/edit/js-87ykxt

However, the countdown itself does not properly work after the first iteration, and behaves strangely, seemingly counting down twice per second, then never actually stopping and going into minus.然而,倒计时本身在第一次迭代后不能正常工作,并且表现得很奇怪,似乎每秒倒计时两次,然后实际上从未停止并进入负数。 The interval is supposed to clear each time the timer reaches 0, then get recreated when the next iteration occurs.间隔应该在每次计时器达到 0 时清除,然后在下一次迭代发生时重新创建。

Any help appreciated.任何帮助表示赞赏。

PS Also aware the first iteration takes 1 minute to begin, and I'll have to fix this too! PS 还知道第一次迭代需要 1 分钟才能开始,我也必须解决这个问题!

Well, I'd avoid using global variables.好吧,我会避免使用全局变量。 Better to pass parameters/values as arguments to functions.最好将参数/值作为 arguments 传递给函数。 And please use 'let' and 'const' instead of 'var'.请使用 'let' 和 'const' 而不是 'var'。 For sake of helping you understand I've shortened your code and added a few debug lines: Hopefully now its functioning as you wished (:为了帮助您理解我已经缩短了您的代码并添加了一些调试行:希望现在它可以按照您的意愿运行(:

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

// Write Javascript code!

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

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

var interval;
var mySeconds;

function tick(task, resolve) {
  var min = Math.floor(mySeconds / 60);
  var sec = mySeconds - min * 60;

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

  var message = min.toString() + ":" + sec;

  console.log(message);

  if (mySeconds === 0) {
    alert("Done for " + task);
    clearInterval(interval);
    return resolve();
  }
  mySeconds--;
}

function resolveTimer(time, task) {
  return new Promise(resolve => {
    mySeconds = time;
    interval = setInterval(tick, 1000, task, resolve);
  });
}

async function startHandler() {
  for (let i = 0; i < todos.length; i++) {
    const time = todos[i].time;
    const task = todos[i].task;

    console.log("Starting for task:", task);
    await resolveTimer(time * 60, task);
    console.log(task, " awaited");
  }
}

This is how you can do, I set the timer to 5s instead of 60s for a better demonstration:您可以这样做,我将计时器设置为 5 秒而不是 60 秒,以便更好地演示:

 const todos = [{ id: 1, task: "Finance", time: 1 }, { id: 2, task: "Distribution", time: 1 }, { id: 3, task: "Blah", time: 1 } ]; const taskDuration = 5; // 5 instead of 60 async function startHandler() { for (const todo of todos) { console.log('Current todo', todo.task); await countDown(todo.time * taskDuration); } } startHandler(); function countDown(time) { function tick() { const min = Math.floor(time / 60); let sec = time - min * 60; if (sec < 10) { sec = "0" + sec; } const message = min.toString() + ":" + sec; console.log(message); time--; } const interval = setInterval(tick, 1000); return promiseSetTimeout(() => clearInterval(interval), time * 1000); } // Util function to call a function later, and return a Promise function promiseSetTimeout(fun, time) { return new Promise(resolve => setTimeout(() => [fun, resolve].forEach(x => x.call()), time)); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM