Saya menulis beberapa Javascript yang berinteraksi dengan kode perpustakaan yang tidak saya miliki, dan tidak dapat (secara wajar) ubah. Ini membuat batas waktu Javascript yang digunakan untuk menampilkan pertanyaan berikutnya dalam serangkaian pertanyaan dengan waktu terbatas. Ini bukan kode nyata karena ia dikaburkan di luar harapan. Inilah yang perpustakaan lakukan:
....
// setup a timeout to go to the next question based on user-supplied time
var t = questionTime * 1000
test.currentTimeout = setTimeout( showNextQuestion(questions[i+1]), t );
Saya ingin meletakkan bilah kemajuan di layar yang terisi questionTime * 1000
dengan menginterogasi pengatur waktu yang dibuat oleh setTimeout
. Satu-satunya masalah adalah, sepertinya tidak ada cara untuk melakukan ini. Apakah ada getTimeout
fungsi yang saya lewatkan? Satu-satunya informasi tentang batas waktu Javascript yang dapat saya temukan hanya terkait dengan pembuatan melalui setTimeout( function, time)
dan penghapusan melalui clearTimeout( id )
.
Saya mencari fungsi yang mengembalikan waktu yang tersisa sebelum batas waktu diaktifkan, atau waktu yang berlalu setelah batas waktu dipanggil. Kode bar kemajuan saya terlihat seperti ini:
var timeleft = getTimeout( test.currentTimeout ); // I don't know how to do this
var $bar = $('.control .bar');
while ( timeleft > 1 ) {
$bar.width(timeleft / test.defaultQuestionTime * 1000);
}
tl; dr: Bagaimana cara menemukan waktu yang tersisa sebelum javascript setTimeout ()?
Inilah solusi yang saya gunakan sekarang. Saya pergi ke bagian perpustakaan yang bertanggung jawab atas tes, dan menguraikan kode (mengerikan, dan bertentangan dengan izin saya).
// setup a timeout to go to the next question based on user-supplied time
var t = questionTime * 1000
test.currentTimeout = mySetTimeout( showNextQuestion(questions[i+1]), t );
dan inilah kode saya:
// wrapper untuk setTimeout function mySetTimeout (func, timeout) { waktu tunggu [n = setTimeout (func, timeout)] = { mulai: Tanggal baru (). getTime (), akhir: Tanggal baru (). getTime () + batas waktu t: batas waktu } kembali n; }
Ini bekerja cukup tepat di browser apa pun yang bukan IE 6. Bahkan iPhone asli, di mana saya mengharapkan semuanya menjadi asynchronous.
sumber
Sebagai catatan, ada cara untuk mendapatkan waktu yang tersisa di node.js:
var timeout = setTimeout(function() {}, 3600 * 1000); setInterval(function() { console.log('Time left: '+getTimeLeft(timeout)+'s'); }, 2000); function getTimeLeft(timeout) { return Math.ceil((timeout._idleStart + timeout._idleTimeout - Date.now()) / 1000); }
Cetakan:
$ node test.js Time left: 3599s Time left: 3597s Time left: 3595s Time left: 3593s
Ini sepertinya tidak berfungsi di firefox, tetapi karena node.js adalah javascript, saya pikir komentar ini mungkin berguna untuk orang yang mencari solusi node.
sumber
getTime()
dihapus,_idleStart
sudah waktunyaEDIT: Saya benar-benar berpikir saya membuat yang lebih baik: https://stackoverflow.com/a/36389263/2378102
Saya menulis fungsi ini dan saya sering menggunakannya:
function timer(callback, delay) { var id, started, remaining = delay, running this.start = function() { running = true started = new Date() id = setTimeout(callback, remaining) } this.pause = function() { running = false clearTimeout(id) remaining -= new Date() - started } this.getTimeLeft = function() { if (running) { this.pause() this.start() } return remaining } this.getStateRunning = function() { return running } this.start() }
Buat pengatur waktu:
a = new timer(function() { // What ever }, 3000)
Jadi jika Anda ingin waktu tersisa lakukan saja:
sumber
Tumpukan acara Javascript tidak beroperasi seperti yang Anda pikirkan.
Saat peristiwa waktu tunggu dibuat, peristiwa itu ditambahkan ke antrean peristiwa, tetapi peristiwa lain mungkin diprioritaskan saat peristiwa itu diaktifkan, menunda waktu eksekusi dan menunda waktu proses.
Contoh: Anda membuat batas waktu dengan penundaan 10 detik untuk mengingatkan sesuatu ke layar. Ini akan ditambahkan ke tumpukan acara dan akan dijalankan setelah semua peristiwa saat ini diaktifkan (menyebabkan beberapa penundaan). Kemudian, saat waktu tunggu diproses, browser masih terus merekam peristiwa lain, menambahkannya ke tumpukan, yang menyebabkan penundaan lebih lanjut dalam pemrosesan. Jika pengguna mengklik, atau melakukan banyak pengetikan ctrl +, acara mereka akan diprioritaskan di atas tumpukan saat ini. 10 detik Anda bisa berubah menjadi 15 detik, atau lebih lama.
Meskipun demikian, ada banyak cara untuk memalsukan berapa lama waktu telah berlalu. Salah satu caranya adalah dengan menjalankan setInterval tepat setelah Anda menambahkan setTimeout ke stack.
Contoh: Lakukan settimeout dengan penundaan 10 detik (simpan penundaan itu secara global). Kemudian lakukan setInterval yang berjalan setiap detik untuk mengurangi 1 dari penundaan dan mengeluarkan sisa penundaan. Karena bagaimana tumpukan peristiwa dapat memengaruhi waktu sebenarnya (dijelaskan di atas), ini masih tidak akurat, tetapi memberikan hitungan.
Singkatnya, tidak ada cara nyata untuk mendapatkan sisa waktu. Hanya ada cara untuk mencoba dan menyampaikan perkiraan kepada pengguna.
sumber
Khusus sisi server Node.js
Tidak satu pun di atas yang benar-benar berhasil untuk saya, dan setelah memeriksa objek batas waktu, sepertinya semuanya relatif terhadap saat proses dimulai. Yang berikut berhasil untuk saya:
myTimer = setTimeout(function a(){console.log('Timer executed')},15000); function getTimeLeft(timeout){ console.log(Math.ceil((timeout._idleStart + timeout._idleTimeout)/1000 - process.uptime())); } setInterval(getTimeLeft,1000,myTimer);
Keluaran:
14 ... 3 2 1 Timer executed -0 -1 ... node -v v9.11.1
Keluaran diedit agar singkatnya, tetapi fungsi dasar ini memberikan perkiraan waktu hingga eksekusi atau sejak eksekusi. Seperti yang disebutkan orang lain, tidak ada dari ini yang akan tepat karena cara proses node, tetapi jika saya ingin menekan permintaan yang dijalankan kurang dari 1 menit yang lalu, dan saya menyimpan pengatur waktu, saya tidak mengerti mengapa ini tidak terjadi. bekerja sebagai pemeriksaan cepat. Mungkin menarik untuk menyulap objek dengan refreshtimer di 10.2+.
sumber
Anda dapat memodifikasi
setTimeout
untuk menyimpan waktu akhir setiap waktu tunggu di peta dan membuat fungsi yang dipanggilgetTimeout
untuk mendapatkan waktu yang tersisa untuk waktu tunggu dengan id tertentu.Ini adalah Super 's solusi , tapi saya dimodifikasi untuk menggunakan memori yang lebih sedikit
let getTimeout = (() => { // IIFE let _setTimeout = setTimeout, // Reference to the original setTimeout map = {}; // Map of all timeouts with their end times setTimeout = (callback, delay) => { // Modify setTimeout let id = _setTimeout(callback, delay); // Run the original, and store the id map[id] = Date.now() + delay; // Store the end time return id; // Return the id }; return (id) => { // The actual getTimeout function // If there was no timeout with that id, return NaN, otherwise, return the time left clamped to 0 return map[id] ? Math.max(map[id] - Date.now(), 0) : NaN; } })();
Pemakaian:
// go home in 4 seconds let redirectTimeout = setTimeout(() => { window.location.href = "/index.html"; }, 4000); // display the time left until the redirect setInterval(() => { document.querySelector("#countdown").innerHTML = `Time left until redirect ${getTimeout(redirectTimeout)}`; },1);
Berikut versi minified dari
getTimeout
IIFE ini :let getTimeout=(()=>{let t=setTimeout,e={};return setTimeout=((a,o)=>{let u=t(a,o);return e[u]=Date.now()+o,u}),t=>e[t]?Math.max(e[t]-Date.now(),0):NaN})();
Saya harap ini berguna bagi Anda seperti bagi saya! :)
sumber
Tidak, tetapi Anda dapat memiliki setTimeout / setInterval Anda sendiri untuk animasi di fungsi Anda.
Katakan pertanyaan Anda terlihat seperti ini:
function myQuestion() { // animate the progress bar for 1 sec animate( "progressbar", 1000 ); // do the question stuff // ... }
Dan animasi Anda akan ditangani oleh 2 fungsi berikut:
function interpolate( start, end, pos ) { return start + ( pos * (end - start) ); } function animate( dom, interval, delay ) { interval = interval || 1000; delay = delay || 10; var start = Number(new Date()); if ( typeof dom === "string" ) { dom = document.getElementById( dom ); } function step() { var now = Number(new Date()), elapsed = now - start, pos = elapsed / interval, value = ~~interpolate( 0, 500, pos ); // 0-500px (progress bar) dom.style.width = value + "px"; if ( elapsed < interval ) setTimeout( step, delay ); } setTimeout( step, delay ); }
sumber
Jika ada yang melihat kembali ini. Saya telah keluar dengan manajer batas waktu dan interval yang dapat memberi Anda waktu yang tersisa dalam batas waktu atau interval serta melakukan beberapa hal lainnya. Saya akan menambahkannya untuk membuatnya lebih bagus dan lebih akurat, tetapi tampaknya berfungsi dengan cukup baik (meskipun saya memiliki beberapa ide lagi untuk membuatnya lebih akurat):
https://github.com/vhmth/Tock
sumber
Pertanyaan telah dijawab tetapi saya akan menambahkan sedikit. Itu baru saja terjadi pada saya.
Gunakan
setTimeout
direcursion
sebagai berikut:var count = -1; function beginTimer() { console.log("Counting 20 seconds"); count++; if(count <20) { console.log(20-count+"seconds left"); setTimeout(beginTimer,2000); } else { endTimer(); } } function endTimer() { console.log("Time is finished"); }
Saya kira kodenya cukup jelas
sumber
Periksa ini:
class Timer { constructor(fun,delay) { this.timer=setTimeout(fun, delay) this.stamp=new Date() } get(){return ((this.timer._idleTimeout - (new Date-this.stamp))/1000) } clear(){return (this.stamp=null, clearTimeout(this.timer))} }
Buat pengatur waktu:
let smtg = new Timer(()=>{do()}, 3000})
Dapatkan tetap:
Hapus waktu tunggu
sumber
(function(){ window.activeCountdowns = []; window.setCountdown = function (code, delay, callback, interval) { var timeout = delay; var timeoutId = setTimeout(function(){ clearCountdown(timeoutId); return code(); }, delay); window.activeCountdowns.push(timeoutId); setTimeout(function countdown(){ var key = window.activeCountdowns.indexOf(timeoutId); if (key < 0) return; timeout -= interval; setTimeout(countdown, interval); return callback(timeout); }, interval); return timeoutId; }; window.clearCountdown = function (timeoutId) { clearTimeout(timeoutId); var key = window.activeCountdowns.indexOf(timeoutId); if (key < 0) return; window.activeCountdowns.splice(key, 1); }; })(); //example var t = setCountdown(function () { console.log('done'); }, 15000, function (i) { console.log(i / 1000); }, 1000);
sumber
Saya mampir di sini mencari jawaban ini, tetapi terlalu memikirkan masalah saya. Jika Anda berada di sini karena Anda hanya perlu melacak waktu saat Anda setTimeout sedang berlangsung, berikut cara lain untuk melakukannya:
var focusTime = parseInt(msg.time) * 1000 setTimeout(function() { alert('Nice Job Heres 5 Schrute bucks') clearInterval(timerInterval) }, focusTime) var timerInterval = setInterval(function(){ focusTime -= 1000 initTimer(focusTime / 1000) }, 1000);
sumber
Cara yang lebih cepat dan mudah:
tmo = 1000; start = performance.now(); setTimeout(function(){ foo(); },tmo);
Anda bisa mendapatkan waktu tersisa dengan:
sumber