I want to run a timer in JavaScript for 30 seconds, play a beeping .WAV file, then count 10 seconds and play the beep again. I want this to repeat until either a desired time is hit or the user intervenes and clicks a stop button.
This is how I've implemented it:
function startWorkOut(param) {
if (param === 1) {
setTimeout(playBeep, 30000); //30 second workout
}
else if (param === 0) {
setTimeout(playBeep, 10000); //10 second rest
}
return;
}
function playBeep() {
beep.play(); //already loaded above this snippet
i++; //simple switch for going back and forth between 30 & 10 secs
if (i % 2 === 1) {
startWorkOut(0);
}
else startWorkOut(1);
return;
}
The problem is I don't know how to stop it. Because these two functions are calling each other back and forth, I need to know how to put in some sort of a manual break.
Assign it to a variable
var beepTimer = setTimeout(playBeep, 30000); //30 second workout
clearTimeout(beepTimer); // This will clear that timer
Try this;
var timerConst;
function startWorkOut(param) {
if (param === 1) {
timerConst = setTimeout(playBeep, 30000); //30 second workout
}
else if (param === 0) {
timerConst = setTimeout(playBeep, 10000); //10 second rest
}
return;
}
function playBeep() {
beep.play(); //already loaded above this snippet
i++; //simple switch for going back and forth between 30 & 10 secs
if (i % 2 === 1) {
startWorkOut(0);
}
else startWorkOut(1);
return;
}
function stop(){
clearTimeout(timerConst);
}
Store the reference returned by setTimeout or setInterval method and then use window.clearTimeout or window.clearInterval to remove those timers. Example:
var ref1 = window.setTimeout(function() {your code}, 5000);
var ref2 = window.setInterval(function() {your code}, 5000);
An then remove them using the following code:
window.clearTimeout(ref1);
window.clearInterval(ref2);
Hope it help.
jsFiddle Demo
"I want to run a timer in JavaScript for 30 seconds, play a beeping .WAV file, then count 10 seconds and play the beep again. I want this to repeat until either a desired time is hit or the user intervenes and clicks a stop button."
Timers are 3 and 1 second for brevity
var playing;//variable for timer
function startWorkOut(){
var entry = playing === void 0;//true if playing is undefined
var interval = entry? 3000 : 1000;//first entry is 3s timer, others are 1s
if(!entry)playBeep();//play a beep except when the workout timer is first started
playing = setTimeout(startWorkOut,interval);//play a beep in either 3s or 1s
}
function stopWorkOut(){
clearTimeout(playing);//stops timer
playing = undefined;//restores variable state
}
Related
I am making a game where there is a 5 seconds countdown, I am doing this countdown on the server side. I want the timer to start over and over again when I send it the request it will respond with the current timer value. For example if 2.2 seconds has passed when the request is made it sends 2.8 seconds as a response and so on. Below you can see my code at the moment, thanks in advance!
router.get("/:result", (req,res) =>{
const result = JSON.parse(req.params.result)
var timerTime = {
time: null
}
if(result.message == "startNewTime"){
//Start the timer
}else if(result.message == "checkingTime"){
//Get the timer value and set it to be the timerTime.time value
//Start the timer from 5 seconds again
res.send(JSON.stringify(timerTime))
}
})
Have you tried setTimeout() ?
You can pass the function or result as first argument and milliseconds as second parameter.
Then you can approach it differently! Try setting a simple counter.
let counter = 0
for(let i = 0; i < 5; I++){
setTimeout(counter++, 1000)
}
Maybe it works this way? You can only track seconds this way though, not milliseconds.
I got it working. The problem I had with the date.now() method was that I was sending a new request and the variable value reset ofc so I just saved it to the session and got it working. Thanks bye!
In my app, I need to run my app offline because drivers have to use that app and in remote areas, they might not find internet for that purpose I need to download all data in advance through Axios request at the time they have internet. so that request can get data from the cache instead of server.
At the moment i tried this but this doesn't seems to be good practice
tryOffileWorkSheet: async function () {
Network.addListener("networkStatusChange", (status) => {
if (status.connected) {
setInterval(function () {
let worksheet = JSON.parse(localStorage.getItem("worksheet"));
if (worksheet == null) {
worksheet = [];
}
// localStorage.removeItem('worksheet')
for (let i = 0; i <= worksheet.length; i++) {
if(worksheet.length > 0){
setTimeout(function () {
if(worksheet[i]?.work_order_id){
ApiService.get(
`/api/gangBoss/work-sheet/${worksheet[i].work_order_id}/${worksheet[i].column_name}/${worksheet[i].value}`
).then((response) => {
if(response.data.status){
worksheet.splice(i,1)
localStorage.setItem("worksheet", JSON.stringify(worksheet));
}
console.log('After', worksheet)
// this.closeModal();
});
}
},i* 3000);
}
}
}, 3000);
}
});
},
also for this, it is necessary for the user to behave on this page when the internet available it means that we need to download a lot of data.
Can you please tell me the best practice to do that or plugin for vue which can help for that
The question is sort of unclear and is not maybe the best fit for SO, but I'll try to answer.
The first thing I noticed here is the use of setInterval, not that you are using it, but rather how. There's nothing that stops the interval from running. Here's a scenario that I hope illustrates the problem
networkStatusChange fired: status.connected === true
setInterval creates interval #1
3 seconds later interval #1 fires
... this keeps happening for the next 2 hours
networkStatusChange fired: status.connected === false
... interval#1 keeps firing
networkStatusChange fired: status.connected === true
setInterval creates interval #2
within 3 seconds interval #1 fires
3 seconds later interval #2 fires
... intervals #1 and #2 keep firing (twice within 3 seconds)
networkStatusChange fired: status.connected === false
networkStatusChange fired: status.connected === true
setInterval creates interval #3
within 3 seconds interval #1 fires
within 3 seconds interval #2 fires
3 seconds later interval #3 fires
... intervals #1, #2 and #3 keep firing (three within 3 seconds)
So there's two problems. The interval keeps firing regardless of whether the system is still connected.
You might be better of just firing every 3 seconds with a single timer, and exiting if the connection is not available. This also allows using window.navigator.onLine, which has much better browser support.
I don't know how long you expect worksheet to be, but if you have the ApiService called through setTimeout 3 seconds apart, and then call the parent function every 3 seconds, you're going to be sending a lot of requests.
tryOffileWorkSheet: function () {
// (need to create `intervalId` in data)
if (this.intervalId) clearInterval(this.intervalId);
this.intervalId = setInterval(() => {
if (window.navigator.onLine) {
this.getWorkSheet();
}
}, 3000);
},
getWorkSheet: function () {
let worksheet = JSON.parse(localStorage.getItem("worksheet"));
if (worksheet == null) {
worksheet = [];
}
for (let i = 0; i <= worksheet.length; i++) {
if (worksheet.length > 0) {
setTimeout(() => {
if (worksheet[i]?.work_order_id) {
ApiService.get(
`/api/gangBoss/work-sheet/${worksheet[i].work_order_id}/${worksheet[i].column_name}/${worksheet[i].value}`
).then((response) => {
if (response.data.status) {
worksheet.splice(i, 1);
localStorage.setItem("worksheet", JSON.stringify(worksheet));
}
console.log("After", worksheet);
});
}
}, i * 300);
}
}
},
I want to start timer after x interval seconds.This x interval seconds will come from server side.
Now i have some process going on server side and on page load i call getData method which starts a timer based on isRunning flag and i display progress
untill i found isRunning false and then stop a timer.
So if user is already on my page where i have 1 schedule jobs which will run after x seconds so i want this getData to call after that x seconds.Right now once user comes on the page getData keeps on going server side for getting progress for schedule jobs.
Hence i was thinking that i will get total seconds of first schedule job and configure my timer to start getData method after x seconds if user doenst refresh the page.
But here i am not getting how to configure $scope.startTimer method in such a way that it will start after x seconds.For eg:If schedule job will run after an hour then start timer method should only start after 1 hour and keep calling getData method every 2 seconds.
Below is my code:
function getData() {
myService.get(function (response) {
if ($scope.isRunning)
$scope.startTimer();
else
$scope.stopTimer();
//response.totalSeconds;here i will get total seconds after which i want to call this method again to show progress of schedule job
});
}
var stop;
$scope.startTimer = function () {
// Don't start a new timer
if (angular.isDefined(stop)) return;
stop = $interval(function () {
if ($scope.refreshTimer > 0) {
$scope.timerLabel = false;
$scope.refreshTimer = $scope.refreshTimer - 1;
} else { //REFERSH CALL
$scope.stopTimer();
getMockProgress();
}
}, 2000);
};
$scope.stopTimer = function () {
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
}
};
Update :
else
$scope.stopTimer();
if (response.milliSeconds > 0)
setTimeout($scope.startTimer, response.milliSeconds);
But this fails to call startTimer method after x milliseconds.
I will appreciate any help :)
Is there any possibilities of capturing tick of each seconds in setTimeout. Say for a scenario I need to logout user after 5 seconds with a message displayed, say in a div, saying "You will be logged out in 5 seconds". then 4,3,2,1 and logout after timeOut
Ex:
setTimeout(function(){
$("#myDiv").text("you will be logged out in " + n + " seconds");
//"n" being tick of each second.
},5000)
I searched over internet for this but nowhere I can see the solution. Or anything that can be done with setInterval for this scenario is also good point here. Any ideas or light on this?
Well you could use the setInterval in conjunction with the clearInterval methods:
var n = 5;
var timeoutID = window.setInterval(function() {
// this callback will execute every second until we call
// the clearInterval method
$('#myDiv').text('you will be logged out in ' + n + ' seconds');
n--;
if (n === 0) {
// TODO: go ahead and really log the dude out
window.clearInterval(timeoutID);
}
}, 1000);
You can have a global variable and use that to show tick. like below
var counter = 5;
var timeInterval= setTimeout(function(){
$("#myDiv").text("you will be logged out in " + n + " seconds");
//"n" being tick of each second.
counter = counter - 1;
clearInterval(timeInterval) if(counter==0)
},1000)
I am having trouble making the following code working properly. The correct behavior should be > on _loadInventory() apply _loadCooldowns() on all .cooldown items (a countdown). This works fine but the problems start when one of the items finishes its cooldown and refreshes the inventory (_loadInventory()). There seems to be an interval stuck that keeps reloading the _loadInventory, breaking the app. I am always clearing all the intervals and even purging the intervals array. I hope the code below will make more sense
// Loading the inventory
function _loadInventory(){
// Fetching the inventory from PHP
_ajaxFetch("php/ajax/conq-get-inventory.php", {ord : 0}).done(function(data){
// Clearing inventory
$('.inventory-field').each(function(){
$(this).html('');
})
// Adding the data to html
$.each(data.html, function(key, value){
$('.inventory-field[data-inventory-field-id="' + key + '"]').html(value);
})
// HERE i am cleaning all the old intervals
$.each(intervals, function(key, value){
clearInterval[intervals[key]];
})
// HERE i am clearing the intervals array
intervals = [];
//buffs = [];
// Teoretically now there should be no intervals, so run the function that assigns the cooldowns for each item in the inventory
_loadCooldowns();
// Other not important code
$('#pesos-wrapper').html(data.pesos);
_startTooltip()
$('#trash-wrapper').droppable({
accept: ".item",
drop: function(event, e){
_ajaxFetch("php/ajax/conq-delete-item.php", {id: e.draggable.attr('data-item-id')}, 1).done(_loadInventory);
e.draggable.remove();
}
});
})
}
Here is the code that applies the cooldown to all the items that have .cooldown class
function _loadCooldowns(){
// If there are any cooldown
if($('.cooldown').length > 0){
// Apply the cooldown for each item
$('.cooldown').each(function(){
// The cooldown element
var e = $(this);
// Just a check
if($(this).attr('data-cooldown-type') == 'item'){
// The id of the item (unique)
var id = $(this).attr('data-item-id');
// Start the interval and save it to the Intevals array
intervals[id] = setInterval(function(){ _applyCooldown(e, id) }, 1000);
}
})
}
}
Here is the actual function inside the Interval
function _applyCooldown(e, id){
// Get the current time in seconds
var time = parseInt(e.attr('data-cooldown'));
// If the time is more than 0
if(time > 0){
// Add new time
if(time > 60){
time--;
e.html(Math.round(time / 60) + 'm');
e.attr('data-cooldown', time);
}
else{
time--;
e.html(time + 's');
e.attr('data-cooldown', time);
}
}
// Otherwise
else{
// Remove this cooldown element
e.remove();
// RELOAD INVENTORY! Here when the inventory is reloaded it should clear all the current intervals and start the full procedure again
// But that does not happen, some intervals get stuck and persist
// Resulting in anonymous intervals being run in the background that keep reloading the inventory all the time as their time is not > 0 (most likely undefined)
_loadInventory();
}
}
}
Any help is appreciated as I am already pulling my hair out. Thanks!!
Fixed!
A really simple fix I think could help a lot of people.
Instead of saving the interval to an array I did the following:
window.interval_id = window.setInterval(function(){ _applyCooldown(e, id) }, 1000);
Now every time I want to reset the intervals I just do
function _resetIntervals(){
for (var i = 1; i <= window.interval_id; i++){
window.clearInterval(i);
window.i = false;
}
}
Works like a charm