Write a function detonatorTimer(delay) that outputs a number to the console every second, starting with delay (integer) and ending with 'Happy New Year!' instead of 0. By setTimeout. There are errors in the code, 0 and the text is output twice.
function detonatorTimer(delay) {
console.log(delay);
if (delay > 0) {
delay --;
setTimeout(detonatorTimer, 1000, delay);
}if(delay === 0) {
console.log('Happy New Year!');
}
}
detonatorTimer(3);
You need to improve a couple of things:
Log the delay conditionally
Use else if instead of just two ifs
Remove the console.log() when invoking the function.
Try with this one:
function detonatorTimer(delay) {
if (delay > 0) {
console.log(delay);
delay --;
setTimeout(detonatorTimer, 1000, delay);
} else if(delay === 0) {
console.log('Happy New Year!');
}
}
detonatorTimer(3);
Related
It became challenging for me to stop executing a recursive function that is used to display a progress bar even after navigating to different component.
animateProgress() {
var counter = this.incrementCounter; //initial value = 0
if (counter <= 100) {
this.updateProgressBar(counter);
setTimeout(()=>{
this.animateProgress();
}, 3000);
this.incrementCounter++;
}
else {
return false;
}
}
updateProgressBar(percentage) {
$('.progressBarDiv').css("width", percentage + "%");
}
I think you should use setInterval since you want that part of code to be repeated multiple times.
animateProgress() {
// removed the local variable counter cause it wasn't really necessary
// setInterval returns an id that you can later use to cancel the interval
const interval = setInterval(() => {
if (this.incrementCounter <= 100) {
this.updateProgressBar();
this.incrementCounter++;
}
else {
// when you reach the condition you clear the inverval
clearInterval(interval);
}
}, 3000);
}
updateProgressBar() {
$('.progressBarDiv').css("width", this.incrementCounter + "%");
}
Otherwise if you wish to stick with setTimeout and recursion this whould work:
animateProgress() {
if (this.incrementCounter <= 100) {
this.updateProgressBar();
this.incrementCounter++;
setTimeout(()=>{
this.animateProgress();
}, 3000);
}
}
Learning some basic concepts in JavaScript "asynchronicity" from Frontendmasters course JavaScript: The Hard Parts, v2
I am given the exercise (Challenge 5):
Create a function limitedRepeat that console logs "hi for now" every second, but only for 5 seconds. Research how to use clearInterval() if you are not sure how to do this.
And following placeholder was given for this function:
function limitedRepeat() {
//CODE HERE
}
I was able to solve it as following (2 versions):
Version 1
function limitedRepeat() {
var totalLogs = 0;
var logFunc = setInterval(myTimer, 1000)
function myTimer() {
if(totalLogs < 5){
console.log("hi for now");
totalLogs++;
} else {
clearInterval(logFunc);
}
}
}
limitedRepeat(); // should log (every second, for 5 seconds): hi for now
Version 2
function limitedRepeat(totalLogs) {
console.log("hi for now");
var timery = setTimeout(timerable,1000);
function timerable() {
totalLogs++;
if(totalLogs >= 5){
clearTimeout(timery);
} else {
limitedRepeat(totalLogs);
}
}
}
limitedRepeat(0); // should log (every second, for 5 seconds): hi for now
Obviously, I have changed the signature of function in Version 2, so I am curious if there is solution that leverages setTimeout() and clearTimeout() and possibly recursion, that doesn't require signature of function to be changed - in other words for that recursive call set by timeout to somehow memorize how many times was the log printed to console?
With recursion;
function limitedRepeat(count = 0) {
if(count >= 5) return;
console.log('hi')
setTimeout(() => limitedRepeat(++count), 1000)
}
limitedRepeat()
Just make sure you increment before recalling the function.
This is my approach:
var count = 1,
timer = setInterval(limitedRepeat,1000)
function limitedRepeat() {
console.log('Hi for now');
count++;
if(count > 5) clearInterval(timer)
}
Using an inner named IIFE with recursion.
EDIT: We don't even need the closure to memoize the times executed if we pass the parameter to the inner function.
function limitedRepeat() {
const maxTimes = 5;
return (function _limitedRepeat(current) {
console.log("hi for now");
var timery = setTimeout(timerable, 1000);
function timerable() {
current++;
if (current >= maxTimes) {
return
}
_limitedRepeat(current);
}
})(0);
}
limitedRepeat();
I am creating a trivia game where a timer counts down as the user attempts to guess the correct answer. I have a function setup to start my unanswered() function below when the timer reaches zero. The unanswered function runs correctly the first time the timer reaches zero but the second time the timer reaches zero I get the error:
Uncaught TypeError: unanswered is not a function at seconds.
function timerHolder() {
clearInterval(clock);
clock = setInterval(seconds, 1000);
function seconds() {
if (timer === 0) {
clearInterval(clock);
unanswered();
} else if (timer > 0) {
timer--;
$('.time').html(timer);
}
}
}
function unanswered() {
unanswered++;
$('.time').html(timer);
$('.main').append("<p class='times-up'>Time's up!</p>");
$('.first-answer').css('background-color', 'green');
$('.times-up')
.delay(2000)
.fadeOut(400);
setTimeout(questionCounter, 2000);
I am trying to check if a variable is equal to 1 using javascript...
myvalue = 1;
function check() {
if (myvalue == 1) {
return setTimeout(check, 1000);
}
alert("Value Is Set");
}
check();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I am planning on adding a delay to the setting of the variable but for now why is this simple version not working?
Using setTimeout(check, 1000); calls the function only once. That's not what you are looking for.
What you're looking for is setInterval which executes a function every n miliseconds.
Look at the below example which waits for the value to be 1, using setInterval, and then clearing the setInterval instance once it does.
Wait 4 seconds when running the snippet below:
// First - set the value to 0
myvalue = 0;
// This variable will hold the setInterval's instance, so we can clear it later on
var interval;
function check() {
if (myvalue == 1) {
alert("Value Is Set");
// We don't need to interval the check function anymore,
// clearInterval will stop its periodical execution.
clearInterval(interval);
}
}
// Create an instance of the check function interval
interval = setInterval(check, 1000);
// Update the value to 1 after 4 seconds
setTimeout(function() { myvalue = 1 }, 4000);
I'm trying to loop 10x over a test (waiting for the condition to be true), but somehow it's not working.
Here is what I have:
// my counter
$.testHelper.countDown = function(test, iteration) {
var ticker = iteration || 0;
if (ticker > 10) {
return false;
}
window.setTimeout(function() {
if (test === true) {
console.log("SENDING");
return true;
}
ticker += 1;
$.testHelper.countDown(test, ticker);
}, 1000);
};
// my test
$.testHelper.testForElement = function(element) {
var result;
console.log($i.find(element).length > 0); // true
result = $.testHelper.countDown(
$i.find(element).length > 0
);
console.log(result); // undefined
return result;
};
My problem is that although my condition equates to true before I'm calling countdown, the answer from countDown is undefined. So my logs come in like this:
// true - before firing my countDown method
// undefined - should not log
// SENDING - response from countDown (= true)
Question:
From the code displayed, is there a reason, why my undefined is logged before countDown is through and returns true?
Thanks!
Erm, because setTimeout is always asynchronous? That's kind of the whole point.
Here's a possibility for you:
function when(condition,then) {
// condition must be a callback that returns `true` when the condition is met
if( condition()) then();
else setTimeout(function() {when(condition,then);},1000);
}
This will poll once every second until the condition is met, and then do whatever is given in the then callback.