Javascript callback cannot assign value in variable - javascript

im new in javascript and i want to make random function to display random image for simple scissor rock paper game,
but i have problem when the callback cannot assign value in variable,
anyone have solution?
thanks before
this is my code
const arr_option = ['scissors', 'rock', 'paper', 'scissors', 'rock', 'paper'];
function random() {
const selector = document.getElementsByClassName('img-komputer')[0];
var i = 0;
var chooseComp = 'Initial Value';
const callback = () => {
var randIndex = Math.floor(Math.random() * arr_option.length);
var comp = arr_option[randIndex];
selector.src = 'img/' + comp + '.png';
if (++i === arr_option.length - 1) {
chooseComp = comp;
clearInterval(refInt);
}
};
const refInt = setInterval(callback, 250);
return chooseComp; // this is value not update
}

Well, as first you're returning compChoose when you updated chooseComp. Btw, js doesn't work in this way, when a value is returned from a method it will not change also if you change into the caller function.
function caller() {
let returnedValue = called();
// here returnedValue is not updated when it's myVar is updated in called function
}
function called() {
let myVar = 12;
setInterval(() => {
// here you are updating myVar but after a copy of this variable is already returned
myVar++;
}, 1000);
return myVar; // here a copy of myVar is created and returned
}
The best option is to use a callback:
function caller() {
// this function inside the parenthesis is the callback
called(function (updatedValue) {
console.log(updatedValue);
});
}
function called(callback) {
let myVar = 12;
callback(myVar);
setInterval(function() {
myVar++;
// create a copy of new value of myVar and use it to call the callback
callback(myVar);
}, 1000);
}
In this way the callback is called every time the myVar is updated and send the new value.
Please let me know if it's clear enough.

I can't see where you define compChoose.

Related

function that makes another function only executable once in JS

I have been working to create a function that given another function will make that second function only callable once. not unlike the _.once() function.
the desired outcome is the following:
const oneTimeFunction = _.once(function(string) { string.split(''); })
oneTimeFunction('hello')
//returns: 'olleh', and if called again it would have no effect returning the same thing a the original call.
Currently this is what I have:
_.once = function (func) {
var called = 0;
let args = null;
if (arguments.length > 1) {
args = Array.prototype.slice.call(arguments,1);
}
return function () {
if (called === 0) {
console.log('being called');
called ++;
if (!args) {
console.log('without apply');
return func.call(arguments);
} else {
console.log('with apply');
return func.apply(this,args);
}
} else {
console.log('this has been called');
return null;
}
};
};
I am running into a wall as it is returning error type undefined even with everything I have tried. Any help, even to get to where it can call the function regardless of the one time only stipulation? Thanks!
create a variable that count how much this function is called
let count = 0;
function once(str) {
if(count < 1){
count++;
return str.split("").reverse().join("");
}
else return str;
}
console.log(once("hello")); // olleh
console.log(once("hello")); // hello
console.log(once("hello")); // hello
In reading your question, I'm seeing that you would like to always return the first value on subsequent calls:
"if called again it would have no effect returning the same thing a[s] the original call."
So I believe you want to do something like this:
function computeOnce(myFn) {
let origVal = undefined;
return function (...args) {
// if this is not set, this is the first call
if (!origVal) {
// execute the function and store it's return value
origVal = myFn(...args);
}
return origVal;
}
}

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;

I can't change global variable inside setInterval es6

I have to find a button when it will appear. In order to do that I use setInterval. When it finds this button, it gives to my variable needed value. I check it inside the setTimeout, but after setTimeout(outside these method) my global variable became as before setTimeout. How to fix that?
let foundValue;
function findById(id) {
let interval = setInterval(() => {
if (document.getElementById(id)){
let foundValue = document.getElementById(id);
clearInterval(interval);
}
}, 1000);
return foundValue;
}
It's because you're re-declaring foundValue inside setInterval so you should remove the second let, for example:
let foundValue;
function findById(id) {
let interval = setInterval(() => {
if (document.getElementById(id)){
foundValue = document.getElementById(id);
clearInterval(interval);
}
}, 1000);
return foundValue;
}

When can a function be only called once?

This problem is giving me trouble:
Write a function, once, (see: http://underscorejs.org/#once) that
takes a function and returns a version of that function which can only
be called once. [Hint: you need a closure] You probably don't want to
be able to double charge someone's credit card. Here is an example of
how to use it:
var chargeCreditCard = function(num, price){
//charges credit card for a certain price
};
var processPaymentOnce = once(chargeCreditCard);
processPaymentOnce(123456789012, 200);
Here's how I tried to solve it:
var once = function(func) {
var invoked = 0;
return function() {
if (invoked === 0) {
invoked++;
return func();
}
};
};
The only problem I can see is you are not passing the arguments to the called function. You can use the arguments object and Function.apply() to do this.
var once = function (func) {
var invoked = 0;
return function () {
if (invoked === 0) {
invoked++;
return func.apply(this, arguments);
}
};
};
Demo: Fiddle
You are almost in the right path but you could also store the return value, pass the args and provide the this context:
function once(func) {
var val,
count = 2;
return function () {
if (--count > 0) {
val = func.apply(this, arguments);
} else {
//performance concern
func = null;
}
return val;
};
}
This is what I have borrowed from lodash to use in my codebase.
It is also worth noting that, passing the count variable as an argument would also let us to use it in a way that the func gets called less than count times

setTimeout is not being called(?)

The issue was my array was [[][][]] instead of [[]] : /
This is my Script
function loopobject(array) {
var me = this;
this.array = array;
this.loop = function() {
counter = 0;
while(array.length > counter) {
window[array[counter]]('arg1', 'arg2');
counter++;
}
setTimeout(function(){ me.loop() }, 100);
}
}
var loopinstant = new loopobject(array);
window.onload = loopinstant.loop();
The problem arises after the first iteration. I don't know exactly the problem but I'm wondering if its due to the fact this is inside an object, and once the function is recreated it doesn't remember the array?
Don't pass a string to setTimeout.
Passing a string to setTimeout causes it to be evaled in global scope.
In addition to being needlessly slow, that means that it won't see your local variables, including the loop variable.
Instead, you should pass a function itself to setTimeout:
setTimeout(function() { loop(array); }, 100);
Also, the loopobject doesn't actually have a loop property that you can call later.
To make a property, change it to this.loop = function(...) { ... }.
Note that the setTimeout callback won't be called with the correct this.
You'll also need to save a copy of this in a local variable.
Finally, your window.onload code will call loop, then assign the result to onload.
Correcting these issues, your code turns into
function loopobject(){
var me = this;
this.loop = function(array){
counter = 0;
while(array.length > counter){
window[array[counter]]('arg1', 'arg2');
counter++;
}
setTimeout(function() { me.loop(array); }, 100);
};
}
var loopinstant = new loopobject();
window.onload = function() { loopinstant.loop(array); };
Replace
setTimeout("loop()", 100);
with
setTimeout(function() { loop(array); }, 100);

Categories

Resources