JS how to get variable that invoked function? - javascript

i would like to get the variable that invoke a function, i'v searched but i didn't find..
To be clearer,
var time = 60
function timer() {
variableName--
console.log(variableName)
return variableName
}
setInterval(() => {
time = timer()
}, 1000)
So, i would like to know variableName, in fact variableName is time so i can do
time = timer(time)
But, it's not very.. i don't know, there is obviously a way to get variable assigned to a function, (i don't know how to say that but i hope you understood me)
So, i want my code to be the more clearest and reusable as posible,
In fact, i'm programing a socket timer,
It's like:
socket.on('timerStart', () => {
TIMER = timer()
console.log(TIMER)
}
function timer() {
if(variableThatInvoked > 0) {
variableThatInvoked--
return variableThatInvoked
}
}
So, how to get variableThatInvoked ?

You could try something like this:
var time = function timer() {
console.log("time called");
}
Below is your async function which uses setTimeout
function async(your_function, callback) {
setTimeout(function() {
your_function();
if (callback) {callback();}
}, 0);
}
async(time, function() {console.log(time);});

It's perfectly fine to do something like
var time = 60
function timer(variableName) {
variableName--
console.log(variableName)
return variableName
}
setInterval(() => {
time = timer(time)
}, 1000)
You can exactly see what you are passing.
And in time = timer() for the function call there's no reference to time at any point

Well, thank you guys, i'v seen that it's not posible, so i'v turned it into class logic
So, for thoses who were like me, there is the Timer class:
class Timer {
constructor(left, rate, func, callback) {
this.left = left
this.rate = rate
this.func = func
this.cb = callback
}
start() {
this.interval = setInterval(() => {
this.func()
this.left--
if(this.left < 0) {clearInterval(this.interval); this.cb()}
}, 1000 / this.rate)
}
}
And so, when a receive a server socket who say 'hey, let's begin the timer !':
socket.on('startTimer', (servLeft) => {
timer = new Timer(servLeft, 2, () => {
console.log(timer.left)
}, () => {console.log('timer ended!')})
timer.start()
})
Logical rendering:
<!DOCTYPE html>
<html>
<head>
<title>Timer</title>
<script>
class Timer {
constructor(left, rate, func, callback) {
this.left = left
this.rate = rate
this.func = func
this.cb = callback
}
start() {
this.interval = setInterval(() => {
this.func()
this.left--
if(this.left < 0) {clearInterval(this.interval); this.cb()}
}, 1000 / this.rate)
}
}
timer = new Timer(20, 1, () => {console.log(timer.left)}, () => {console.log('Timer ended!')})
timer.start()
</script>
</head>
<body>
<hi>Simple timer</hi>
</body>
</html>

Related

JavaScript Scoping Can't Access setInterval

Hey guys can someone just quickly help me out here.
I have an interval for a slideshow in one function and I want to clear it from another function without using global scopes as I know it is bad practice.
Can someone kindly help here please?
function beginSlideshow() {
var interval = setInterval(function () {
//Slideshow content here
}
function revertSlideshow() {
clearInterval(interval);
}
You have to store the timer handle somewhere. :-)
You have lots of options:
Modules
You could use modules. Then a top-level declaration of interval wouldn't be a global, it would only be accessible to the module:
let interval = 0;
export function beginSlideshow() {
interval = setInterval(function () {
//Slideshow content here
}, someValue);
}
export function revertSlideshow() {
clearInterval(interval);
interval = 0;
}
In a closure's scope
Similar concept to the module above, but without using modules:
const { beginSlideshow, revertSlideshow } = (() => {
let interval = 0;
function beginSlideshow() {
interval = setInterval(function () {
//Slideshow content here
}, someValue);
}
function revertSlideshow() {
clearInterval(interval);
interval = 0;
}
return { beginSlideshow, revertSlideshow };
})());
In the caller's scope
You could make this the problem of the person calling beginSlideshow by returning the function to stop it:
function beginSlideshow() {
const interval = setInterval(function () {
//Slideshow content here
}, someValue);
return () => {
clearInterval(interval);
};
}
The caller would use that like this:
const revertSlideshow = beginSlideShow();
// ...
revertSlideshow();
Another way to store it in the caller's scope is to wrap this up in a class and have the handle be a data property:
class Slideshow {
interval = 0;
begin() {
this.interval = setInterval(/*...*/);
}
revert() { // I'd call it "end"
clearInterval(this.interval);
this.interval = 0;
}
}

debounce function not working in javascript

I'm having problem understanding why the below debounce code does not work?
you can see the below code in the following: link
`
HTML:
<input type="text" onkeyup="betterFunction(event)"/>
JS:
let newValue;
let counter = 0;
const getData = () => {
// dummy call to API and get Data
console.log("Fetching Data ..", newValue,counter++);
}
const debounce = function (fn, d) {
let timer;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
fn();
}, d);
}
}
const betterFunction = ({target:{value}}) => {
newValue=value;
debounce(getData, 2000); // **line 1**. placing this line of code debouncing does not happen
intermediate() // **line 2**. replacing this line of code with the above line debouncing works
}
const intermediate = debounce(getData, 2000);
`
I understand that the debounce function returns another function which acts like a closure in JavaScript but why the above line 1 code does not work but the line 2 code works
debounce function returns a function which is never called when you call debounce as
debounce(getData, 2000);
dobounce function doesn't needs to return a function. You just need following steps to implement debounce function:
Check if timer is undefined or not. If not, that means there's a timeout that we need to cancel.
After that set a new timer by calling setTimeout() that calls the given function after specific amount of time.
Also, timer should not be a local variable because you don't want it to reset whenever debounce function is called.
let counter = 0;
let newValue;
let timer;
const getData = () => {
console.log("Fetching Data ..", newValue, counter++);
}
const debounce = function(fn, d) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(fn, d);
}
const betterFunction = (e) => {
newValue = e.target.value;
debounce(getData, 2000);
}
<input type="text" onkeyup="betterFunction(event)" />
If you don't want to declare timer as a global variable and want to return a function from debounce function, then you need to call the debounce function once initially and whenever keyup event fires on the input element, you call the function returned from the debounce function instead of calling the debounce function.
let counter = 0;
let newValue;
const getData = () => {
console.log('Fetching Data ..', newValue, counter++);
};
const debounce = function(fn, d) {
let timer;
return function() {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(fn, d);
};
};
const intermediate = debounce(getData, 2000);
const betterFunction = (e) => {
newValue = e.target.value;
intermediate();
};
<input type="text" onkeyup="betterFunction(event)" />
i hope that what you want :
let counter = 0;
// you need to define timer and newValue here first
let timer , newValue;
// defining input as varible for good usage better than usage in html
var input = document.querySelector("#inp");
const getData = () => {
// increment first better than in console :)
counter+=1;
console.log("Fetching Data .." , newValue , counter);
// as last step clear timer for next timeout
clearTimeout(timer);
}
// givin value direct to timer directlly worked better than return
const debounce = function (fn, d) {
timer = setTimeout(fn, d);
}
const betterFunction = () => {
// newvalue must equal input value
newValue = input.value;
// and then calling debounce as last step
debounce(getData, 2000);
}
// here giving onkeyup event to input for getting values and start working :)
input.onkeyup = betterFunction;

How to Prevent Timeout Function from Running Twice

I am trying to automatically pass data from an input field into a function if no new data has been entered after 1000 ms. However, its behavior is inconsistent and sometimes the function runs twice on a single input.
<paper-input id="itemId" on-input="automaticInput"></paper-input>
...
automaticInput() {
let timeout = null;
let that = this;
console.log(timeout); // logging each keystroke
input();
function input() {
console.log('input');
clearTimeout(timeout);
timeout = setTimeout(function() {
that.validateInput();
}, 1000);
}
}
validateInput() {
if (this.$.itemId.value) {
this.doSomething(); // runs twice
}
}
How do can I properly set the automaticInput function to only run once per input string?
What you need is a debounce function. Your code is mostly here, just move timeout var out of automaticInput:
let timeout = null;
automaticInput() {
clearTimeout(timeout);
let that = this;
timeout = setTimeout(function() {
that.validateInput();
}, 1000);
}
Or better create debounce fn like:
function debounce(fn, timeout = 0) {
let timeoutId = null;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), timeout);
}
}
and then you code become:
const debouncedValidateInput = debounce(this.validateInput.bind(this), 1000);
<paper-input id="itemId" on-input="debouncedValidateInput"></paper-input>
If you use something like lodash it already shipped with such helper.

how to execute a function that inside it is another function and pass params

I have a function like this :
$.SetInLocalStorageVideoTime = function (uuid) {
alert(uuid);
var Interval = setInterval(function () {
localStorage.setItem('poption-ctime-'+ uuid , jwplayer("target").getPosition());
},10000);
var ClearInterVal = clearInterval(Interval);
return {
Interval : Interval,
ClearInterVal : ClearInterVal
}
};
My problem is how to call the Interval function and pass uuid param to that.
I have tried $.SetInLocalStorageVideoTime("blahblah").Interval(); but it throws an error.
var Interval = setInterval(...)
This immediately calls the setInterval function and assigns its return value to Interval; same for clearInterval. You don't want to call the function, you want to create a function which when called calls the function. Two ways to do that:
var Interval = function () {
setInterval(...);
}
var Interval = setInterval.bind(null, ...);
Putting it all together, you want this:
$.SetInLocalStorageVideoTime = function (uuid) {
var interval = null;
var set = function () {
interval = setInterval(function () {
localStorage.setItem('poption-ctime-'+ uuid , jwplayer("target").getPosition());
}, 10000);
};
var clear = function () {
clearInterval(interval);
};
return {
Interval : set,
ClearInterVal : clear
}
};
Look this plunker : https://plnkr.co/edit/7H61Vv6m8M552CNeIpSA?p=preview
You must encapsulate into function :
var stop;
var interval = function () {
stop = setInterval(function () {
console.log(uuid);
},100);
}
var ClearInterVal = function () { clearInterval(stop) };
You have several simple issues, you must export function that will clearTimeout
$.SetInLocalStorageVideoTime = function(uuid) {
// auto start interval, you could
// add starter function or something
var Interval = setInterval(function() {
localStorage.setItem('poption-ctime-' + uuid, jwplayer("target").getPosition());
}, 10000);
// clear function
// exported
var ClearInterVal = function() {
if (Interval)
clearInterval(Interval);
}
return {
// Interval is not required here
ClearInterVal: ClearInterVal
}
};
$.SetInLocalStorageVideoTime();

How to disable a function when time passed?

I'm trying to disable 2 functions when a certain time period is reached and enable the other 2 after that time period. So the second 2 functions would have to be disabled to begin with.
I was thinking of using the following code to wrap around the functions:
Code:
var startTime = new Date().getTime();
var interval = setInterval(function(){
if(new Date().getTime() - startTime > 5000){
clearInterval(interval);
return;
}
function 1() {}
$(function 2() {});
}, 1000);
function 3() {}
$(function 4() {});
Can you help?
If you want to control whether functions do something or not, based on how much time has elapsed, it would probably be easier to set a flag after the interval you need, and then have your functions check that flag to decide if they are going to do something:
var timedOut = false;
setTimeout(function () {
timedOut = true;
}, 5000);
function one() {
if (!timedOut) {
// do something
}
}
function two() {
if (!timedOut) {
// do something
}
}
function three() {
if (timedOut) {
// do something
}
}
function four() {
if (timedOut) {
// do something
}
}
This should get you started; I've simply redefined the original func1/func2 functions after a set time (5 seconds, as your example uses). This could do any number of things (such as remove the function definition altogether).
(function(document,window,undefined){
// Used simply to show output to the window.
var db = document.getElementById('db');
// Here we define the initial state of our two functions.
// Nothing magical here, just outputting a description.
window.func1 = function(){
db.innerHTML += 'Hello from original func1\r\n';
}
window.func2 = function(){
db.innerHTML += 'Hello from original func2\r\n';
}
// Here we keep the same format you used (using the Date to
// define when one's been deprecated over the other).
var startTime = new Date().getTime(),
interval = setInterval(function(){
var currentTime = new Date().getTime(),
delta = currentTime - startTime;
if (delta > 5000){
// In here, now that the specified amount of time has
// elapsed, we redefine the meaning of the two original
// functions. We could also simply remove them.
window.func1 = function(){
db.innerHTML += 'Hello from NEW func1\r\n';
}
window.func2 = function(){
db.innerHTML += 'Hello from NEW func2\r\n';
}
clearInterval(interval);
}
}, 1000);
})(document,window);
// This is here just to show you how one definition is changed
// in place of another.
setInterval(function(){
func1();
func2();
}, 1000);
<pre id="db"></pre>
If you mean 'disabling' the functions after certain amount of seconds then this should do the trick.
var secondsLimit = 10,
a = 0,
b = setInterval(function () { a += 1; }, 1000 });
function A() {
if (a > secondsLimit) {
return;
}
// do stuff
}
You can change the functions if you call them e.g. by a global variable scope.
In the following example based on your code, the functions switch after 4 seconds.
var function1 = function() {
console.log("function 1 active");
};
var function2 = function() {
console.log("function 2 active")
}
var startTime = new Date().getTime();
setTimeout(function() {
function1 = function() {
console.log("now function 3 is active instead of function 1");
}
function2 = function() {
console.log("now function 4 is active instead of function 2");
}
}, 4000);
//the following code is just for testing reasons
var interval = setInterval(function() {
function1();
function2();
}, 1000)

Categories

Resources