Pass a parameter into a function setting a setTimeout? - javascript

Is there a way I can call this from another module specifying the timeout in brackets?
var addActiveDiv = () => {
var activeEl = document.querySelector(".o-wrapper");
setTimeout(() => {
activeEl.classList.add("is-active");
}, 1850);
}
addActiveDiv();
export { addActiveDiv }
Something like
addActiveDiv(2000); where 2000 is the new timeout?

Just specify the function as taking a parameter, and pass that parameter to setTimeout?
var addActiveDiv = (ms) => {
var activeEl = document.querySelector(".o-wrapper");
setTimeout(() => {
activeEl.classList.add("is-active");
}, ms);
}
addActiveDiv(2000);
export { addActiveDiv }

Use parameters or default parameters.
var addActiveDiv = (timeout = 1850) => {
var activeEl = document.querySelector(".o-wrapper");
setTimeout(() => {
activeEl.classList.add("is-active");
}, timeout);
}
addActiveDiv();
export { addActiveDiv }
import { addActiveDiv } from "foobar";
addActiveDiv(2000);

Related

How do these nested JavaScript functions work?

I have a question related to this code:
const somaHorasExtras = (salario, valorHorasExtras) => salario + valorHorasExtras;
const calculaDescontos = (salario, descontos) => salario - descontos;
const verifiqueSe = (valor) => {
const assercoes = {
ehExatamenteIgualA(esperado) {
if (valor !== esperado) {
// eslint-disable-next-line no-throw-literal
throw {};
}
},
};
return assercoes;
};
const teste = (titulo, funcaoDeTeste) => {
try {
funcaoDeTeste();
console.log(`${titulo} passou!`);
} catch {
console.error(`${titulo} não passou!!!`);
}
};
teste('somaHorasExtras', () => {
const esperado = 2500;
const retornado = somaHorasExtras(2000, 500);
verifiqueSe(retornado).ehExatamenteIgualA(esperado);
});
teste('calculaDesconto', () => {
const esperado = 2300;
const retornado = calculaDescontos(2500, 200);
verifiqueSe(retornado).ehExatamenteIgualA(esperado);
});
My question is related to the verifiqueSe function specifically. How does this function work? Does someone can explain how this function work in conjunction with the inner function ehExatamenteIgualA? What is the assercoes which is returned?
Thank you.
Your verifiqueSe(valor) function returns an object. You may find it a little confusing, since this syntax:
const foo = {
bar() {
//
}
};
is just a short syntax for object method:
const foo = {
bar: function () {
//
}
};
So in order to call the bar() function, you'd need to reach it through foo:
foo.bar();

Integrating debounce to search input

I am trying to integrate debounce to a search input so i can search through fetched data (after getting the data ) with the full term, i have this debounce function in the App.js :
debounce = (callback, delay) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => callback(...args), delay);
}
}
debouncedTerm = this.debounce(text => console.log(text), 300);
I have also this method in the App.js
onSearchChanged = data => {
const searchBar = data.target.value.toLowerCase();
this.debouncedTerm(searchBar)
this.setState({
searchBar: searchBar,
}, () => {
let newData = {...this.state};
if( typeof this.props.source !== "undefined"){
newData.source = this.props.source
}
newData.params = {
searchBar : this.state.searchBar
}
Api.fetchQuestions(newData.params)
.catch( error => {
if (typeof error.message !== "undefined"){
newData.config.formMessage = {
message : error.message,
success : false,
}
newData.widgetStatus = false;
this.setState(newData)
}
return {data:{data:[]}}
})
.then( response => {
if(response.data.status === 'success'){
return response.data.data;
}
this.setState({
questions: [...response.data.questions.items],
loading: false
});
})
});
};
FYI : I pass the value of the input (searchBar) as a parameter in newData.params
'URL/questions?client_id='+params.client_id+'&term='+params.searchBar,
How can i integrate debouncedTerm in the method onSearchChanged
I have the search input in a child component
<InputSearch
type="search"
placeholder="Search"
onChange={props.searchCallback}
/>
this is a part of the code I wrote recently:
export function debounceFetch(fn, delay) {
let createdTimeout;
let controller;
function onCancel() {
controller?.abort();
createdTimeout?.cancel();
}
async function debounced(...args) {
onCancel();
controller = new AbortController();
createdTimeout = timeout(delay);
await createdTimeout.delay;
return fn(...args, controller.signal);
}
return [
debounced,
onCancel,
];
}
It cancels the fetch request too,
and this is the timeout part:
function timeout(ms) {
let timeoutRef;
let rejectRef;
const delay = new Promise((resolve, reject) => {
timeoutRef = setTimeout(() => {
resolve('timeout done');
}, ms);
rejectRef = () => {
reject(new Error('cancel timeout'));
};
});
return {
delay,
cancel() {
clearTimeout(timeoutRef);
rejectRef();
},
};
}

JavaScript - Map of Objects applies function only on last object (possible hoisting issue)

I have created a WebPage function that should act as a class.
I have a map of url keys and WebPage object values and I want to call a method on each object. The method, called startMonitoring should set an interval to a variable scoped to each object.
However, the interval is set only on the last object and every other object will get the same output when printed afterwards.
Here is my code:
export const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
export function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
...
WebPage.prototype.startMonitoring = () => {
this.scheduledTask = setInterval(async () => {
// asynchronous work
}, checkTime * 1000);
};
}
This happens because you are setting the prototype each time your create a new object. So all instances will access the last one you define.
And you will, now, have to use regular functions to have access to the correct this.
export const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
export function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.checkTime = checkTime;
...
}
WebPage.prototype.startMonitoring = function() {
this.scheduledTask = setInterval(async function() {
// asynchronous work
}, this.checkTime * 1000);
};
As Pointy said, using the prototype, this would work:
const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.url = url;
WebPage.prototype.startMonitoring = function() {
this.scheduledTask = setInterval(async () => {
console.log('hello', this.url);
}, checkTime * 1000);
};
}
const websites = [new WebPage('#', 1), new WebPage('#test', 1)]
startMonitoring(websites);
Also, changing the prototype function should also work:
const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.url = url;
this.startMonitoring = () => {
this.scheduledTask = setInterval(async () => {
console.log('hello', this.url);
}, checkTime * 1000);
};
}
const websites = [new WebPage('#', 1), new WebPage('#test', 1)]
startMonitoring(websites);

React setTimeout and clearTimeout

Recently I am creating a website using React and I found out that I kind of use a lot of 'setTimeOut()' and I know that from React documentation sometimes you need to clean up some things when component unmount(To be honest, I am not fully understand about this clean up thing), apparently recently I saw a posts saying that 'setTimeOut()' need to be clean up too but how do I clean up functions that I call in 'useEffect()' which I am using 'setTimeOut()' inside the function?
Here are my codes:
useEffect(() => {
createContent();
handleMobileContainerView();
});
const createContent = () => {
if (contentCompShowStatus) {
for (let key in btnStatus) {
if (btnStatus.hasOwnProperty(key)) {
if (btnStatus[key] === true) {
if (key === 'aboutBtn') {
delayContent('about-contents');
} else if (key === 'skillsBtn') {
delayContent('skills-contents');
} else if (key === 'projectsBtn') {
delayContent('projects-contents');
}
}
}
}
}
};
const delayContent = (content) => {
if (firstTime) {
setTimeout(() => {
setCurrentContent(content);
setFirstTime(false);
}, 200);
} else if (!firstTime) {
setTimeout(() => {
setCurrentContent(content);
}, 450);
}
};
As you can see above codes, 'createContent()' is in 'useEffect()' and is calling a function name 'delayContent()' which is using 'setTimeout()'.
Do I need to do clean up with this kind of case?
How do I do clean up with this kind of case? (function inside of function which is using 'setTimeOut()' and is called in 'useEffect()')
You can return timerId while creating timeOut. And on unmount u can clean using return function of useEffect.
Unmount:
useEffect(() => {
const timerId = createContent();
handleMobileContainerView();
return () => {
clearTimeout(timerId);
};
}, []);
Return TimerId:
const delayContent = (content) => {
let timerId;
if (firstTime) {
timerId = setTimeout(() => {
setCurrentContent(content);
setFirstTime(false);
}, 200);
} else if (!firstTime) {
timerId = setTimeout(() => {
setCurrentContent(content);
}, 450);
}
return timerId;
};
// All code:
function A() {
useEffect(() => {
const timerId = createContent();
handleMobileContainerView();
return () => {
clearTimeout(timerId);
};
}, []);
const createContent = () => {
if (contentCompShowStatus) {
for (let key in btnStatus) {
if (btnStatus.hasOwnProperty(key)) {
if (btnStatus[key] === true) {
if (key === "aboutBtn") {
return delayContent("about-contents");
} else if (key === "skillsBtn") {
return delayContent("skills-contents");
} else if (key === "projectsBtn") {
return delayContent("projects-contents");
}
}
}
}
}
};
const delayContent = (content) => {
let timerId;
if (firstTime) {
timerId = setTimeout(() => {
setCurrentContent(content);
setFirstTime(false);
}, 200);
} else if (!firstTime) {
timerId = setTimeout(() => {
setCurrentContent(content);
}, 450);
}
return timerId;
};
}
You can use useEffect to return a function which should do the job of cleaning up of the setTimouts and setIntervals. For eg,
useEffect(() => {
const timer = setTimeout(someFunc, 100);
return () => clearTimeout(timer);
});
To cleanup setTimouts, use clearTimeout and clearInterval for setInterval. Documentation
As far as your code is concerned,
useEffect(() => {
const timers = createContent();
handleMobileContainerView();
return () => timers.forEach(timer => window.clearTimeout(timer));
});
const createContent = () => {
let timers = [];
if (contentCompShowStatus) {
for (let key in btnStatus) {
if (btnStatus.hasOwnProperty(key)) {
if (btnStatus[key] === true) {
if (key === 'aboutBtn') {
timers.push(delayContent('about-contents'));
} else if (key === 'skillsBtn') {
timers.push(delayContent('skills-contents'));
} else if (key === 'projectsBtn') {
timers.push(delayContent('projects-contents'));
}
}
}
}
}
return timers;
};
const delayContent = (content) => {
let timer;
if (firstTime) {
timer = setTimeout(() => {
setCurrentContent(content);
setFirstTime(false);
}, 200);
} else if (!firstTime) {
timer = setTimeout(() => {
setCurrentContent(content);
}, 450);
}
return timer;
};

How do i prevent endless loop in while loop in action creator?

Trying to implement some kind of game loop, that will run until conditions are met.
However during testing I just can't solve the problem of while loop not waiting for resolve of promises, instead it just calls them over and over again causuing browser to crash.
The combatStart() is called when component is mounted
export const combatStart = () => {
return function (dispatch, getState) {
while (getState().mechanics.noOfEnemiesAttacked < 5) {
let setTimeoutPromise = new Promise(resolve => {
let success = true;
setTimeout(function () { resolve(success) }, 3000);
})
setTimeoutPromise.then((resp) => {
if(resp){
dispatch({
type: 'INCREMENT_ENEMIES_ATTACKED'
})
}
})
}
}
}
When i dispatch the action the "noOfEnemiesAttacked" increments, and when it reaches 5 the loop should stop. So it should last around 15 seconds.
The code works until I add the while loop, otherwise it works as expected, increments the value after 3 seconds when component is mounted.
How can I make this work?
Recursively doesnt work, it doesnt loop, just goes once:
export const combatStart = () => {
return function (dispatch, getState) {
let setTimeoutPromise = new Promise(resolve => {
let success = true;
setTimeout(function () { resolve(success) }, 2000);
})
setTimeoutPromise.then((resp) => {
if (resp) {
dispatch({
type: 'INCREMENT_ENEMIES_ATTACKED'
})
}
if (getState().mechanics.noOfEnemiesAttacked < 5) {
console.log(getState().mechanics.noOfEnemiesAttacked)
combatStart();
}
})
}
}
Wrapped it in a function, now it should work
export const combatStart = () => {
return function (dispatch, getState) {
function foo(){
let setTimeoutPromise = new Promise(resolve => {
let success = true;
setTimeout(function () { resolve(success) }, 2000);
})
setTimeoutPromise.then((resp) => {
if (resp) {
dispatch({
type: 'INCREMENT_ENEMIES_ATTACKED'
})
}
if (getState().mechanics.noOfEnemiesAttacked < 5) {
console.log(getState().mechanics.noOfEnemiesAttacked)
combatStart();
foo();
}
})
}
foo();
}
}

Categories