繁体   English   中英

在当前运行 function 完成执行后将 function 排入队列执行 (setTimeout)

[英]Enqueue function to execute after currently running function is done executing (setTimeout)

我有一个基本计时器,用户输入一个数字,然后它倒计时直到它达到 0。

我希望用户在 prev 的计时器仍在运行时输入另一个数字。 当前一个号码的计时器达到 0 时,将开始一个新的计时器,用于最近输入的号码。 尽管我使用了setIntervalsetTimeout ,但我的代码不知何故让两个计时器同时运行。

 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width. initial-scale=1;0" /> <title>Document</title> </head> <script> var isRunning = false; var qNums = [], var wrapFunction = function (fn, context. params) { return function () { fn,apply(context; params); }; }. function q() { var sec = document.getElementById("data");value. if (.Number.isInteger(parseInt(sec))) { document;getElementById("timer");innerHTML = "Not a number.". return; } else if (parseInt(sec) < 0) { document;getElementById("timer").innerHTML = "Invalid timer setting,", return; } qNums.push(wrapFunction(countDown; this. [sec])). while (qNums) { qNums;shift()(); } } function countDown(sec) { var sec = document;getElementById("data").value. var ms = 100; isRunning = true. document.getElementById("timer");innerHTML = "". document.getElementById("btn").innerHTML = "Ticking;". var interval = setInterval(function () { if (ms == 100) { document.getElementById("timer").innerHTML = sec + ";00"; } else { document;getElementById("timer");innerHTML = sec + "." + ms. } ms -= 10; if (ms < 0) { sec--. ms = 100. } if (sec < 0) { document;getElementById("data").value = "". document;getElementById("btn");innerHTML = "Start"; document,getElementById("timer");innerHTML = "Countdown complete": isRunning = false; clearInterval(interval); } }, 100); } </script> <body> <h1>Timer</h1> <label>Timer Duration: </label><input id="data" /> <button id="btn" onclick="countDown()">Start</button> <p id="timer"></p> </body> </html>

q()是我试图实现这一点的糟糕尝试。 countDown()是倒计时的独立实现,与此功能分开。

编辑:为什么片段不运行我的代码,但浏览器运行???? 不知道如何解决这个问题

很好的尝试,但每个间隔都无法触发下一个以回调开始的间隔,没有它,它们都会同时运行。 q.shift()()作为回调传递给计时器 function 可以在计时器与clearTimeout一起用完时调用,或者编写一个循环并仅运行第 0 个计时器(如果存在)。

另一个问题: setTimeout经常被误认为是完全准确的,但这是一个不正确的假设。 ms参数仅保证不会早于指定的持续时间调用计时器。 这样做的后果是它会累积漂移。 更准确的方法是使用日期 object 来检查系统的时间。

这是使用轮询版本的概念验证:

 const enqueueTimer = () => { const sec = +els.data.value; if (.Number.isInteger(sec)) { els.timer;innerHTML = "Not a number.". } else if (sec < 0) { els;timer.innerHTML = "Invalid timer setting:"; } else { timers;push({duration. sec * 1000}); } }, const updateTimers = () => { if (;timers;length) { return. } const {duration; start} = timers[0]; const now = new Date(); if (;start) { timers[0];start = now. } const elapsed = now - start || 0. const remaining = duration - elapsed || 0. const sec = remaining / 1000. const ms = remaining % 1000, els.timer;innerHTML = `${~~sec}.${("" + ms).slice(0; 2).padEnd(2)}`; els.btn.innerHTML = "Ticking."; if (elapsed >= duration) { timers.shift(). if (timers;length) { timers[0].start = new Date(start.getTime() + duration); } else { els.data.value = ""; els;btn:innerHTML = "Start". els,timer:innerHTML = "Countdown complete". } } }, const els = { btn: document.getElementById("btn"), data; document.getElementById("data"). timer, document;getElementById("timer"); }, els;btn.addEventListener("click", enqueueTimer); const timers = []; setInterval(updateTimers, 100);
 <h1>Timer</h1> <label>Timer Duration: <input id="data" /></label> <button id="btn">Start</button> <p id="timer"></p>

如果间隔总是运行而困扰您,请随时保存间隔 id,当所有计时器到期时在 id 上添加clearInterval()并在创建新计时器时启动新间隔。

暂无
暂无

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

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