簡體   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