This question already has answers here:
stop settimeout in recursive function
(7 answers)
Javascript delete a function
(3 answers)
Closed 2 years ago.
const resumeInfinity = () => {
window.speechSynthesis.resume();
const timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
console.log(timeoutResumeInfinity);
}
utterThis.onstart = () => {
resumeInfinity();
};
need the (resumeInfinity) function to stop working after the speechSynthesi
To avoid error messages that resumeInfinity is not a function you shouldn't delete it but set it to an empty function. But as you set defined resumeInfinity as const you can't change that function.
So what you can do is to either change it to:
let resumeInfinity = () => {
// ... your code
}
And then do change it later to an empty function resumeInfinity = () => {}
But you need to keep in mind that if that original function was passed as callback earlier to somewhere else (e.g. like here setTimeout(resumeInfinity, 1000)) that this callback will still refer to the old function.
So a better solution would be to check if the function should still valid to be executed and do an early out otherwise.
const resumeInfinity = () => {
if( /* some check if isn't valid to call that function anymore */ ) {
return
}
window.speechSynthesis.resume();
const timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
console.log(timeoutResumeInfinity);
}
But all of these above solutions are in fact just a workaround, because if the logic of your application is correct then such a situation should never happen. So the need to do something like this indicates that you more likely need to think about restructuring your code.
If it is just about stopping the timeout then you need to call clearTimeout(timeoutResumeInfinity), and make timeoutResumeInfinity available at the place at which you know that the speechSynthesi finished.
Related
This question already has answers here:
JavaScript setInterval and `this` solution
(9 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 5 months ago.
I try to store Date.now() after a setIntervall invoked a callback. After that, I'd like to clear the intervall, so it only fires once. All that in a class.
But the variable I store the intervalID in and I hoped would be available "class-wide" keeps "undefined". I am pretty sure I am doing sth awfully wrong with JS scope, but I cannot find out what.
class Signal {
t : number;
private intervallId : number | undefined;
constructor(t : number) {
this.t = t;
}
wait() {
this.intervallId = setInterval(this.signalTriggered, this.t)
console.log("Never executed.")
}
signalTriggered() {
const triggerTime : number = Date.now()
console.log(this.intervallId) /* always undefined */
if (this.intervallId) {clearInterval(this.intervallId)
console.log(triggerTime); }
}
}
var timer = new Signal(2000)
timer.wait()
console.log("Done.") /* Never printed out. */
The problem is the reference of the this, you are losing the original reference of it when passing the method as an argument to setIterval.
You could use an arrow function to wrap the method:
setInterval(() => this.signalTriggered(), this.t)
Or use Function.prototype.bind to assign the reference of this:
setInterval(this.signalTriggered.bind(this), this.t)
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 3 years ago.
I've setup a carousel with Materialize framework, now i would like to show some text with the mouseenter event, but it's seems it doesn't work. the display of my text is still none, and i have an error "TypeError: infos[i] is undefined".
The console.log(infos[i]) is working and the concerned divs have the display none attributes so i guess the problem comes from the line elem.addEventListener('mouseenter', function(){
infos[i].style.display="block"
})
M.AutoInit();
document.addEventListener('DOMContentLoaded', function () {
let interval = null
const timeInterval = 5000
const elem = document.querySelector('.carousel')
const carousel = M.Carousel.getInstance(elem, {
indicators: true
})
const iterate = () => carousel.next()
const init = () => setInterval(iterate, timeInterval)
interval = init()
elem.addEventListener('mouseenter', () => clearInterval(interval))
elem.addEventListener('mouseleave', () => {
interval = init()
})
var infos = document.querySelectorAll('.infos');
for (i = 0; i<infos.length;i++){
infos[i].style.display="none"
//console.log(infos[i])
elem.addEventListener('mouseenter', function(){
infos[i].style.display="block"
})
}
})
You have a single global i variable which is being used by every one of the event listeners. By the time an event listener gets called, i has long since been incremented to infos.length, and infos[infos.length] is undefined. Instead create a local variable with let.
for (let i = 0; i<infos.length;i++){
let will cause it to get a new binding each time through the loop, and so each of the event listeners will be interacting with its own personal instance of i, and thus will interact with the correct element. Ps, make sure not to use var, or you'll be back to the same problem.
This question already has answers here:
What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript?
(14 answers)
Closed 4 years ago.
What is the use of 'cb => cb(snapshot)' ?
if (this._snapshotCallbacks.length > 0) {
const snapshot = gl.canvas.toDataURL();
this._snapshotCallbacks.forEach(cb => cb(snapshot));
this._snapshotCallbacks = [];
}
requestSnapshot (callback) {
this._snapshotCallbacks.push(callback);
}
this._snapshotCallbacks.forEach(cb => cb(snapshot));
can be rewritten as
this._snapshotCallbacks.forEach(function (callback) {
callback(snapshot)
});
i think it's clear when there is no arrow function?
this._snapshotCallbacks.forEach(cb => cb(snapshot));
means there is a collection of callbacks and the code here invokes them one after each other.
forEach is a function that exists on the array prototype that will take a function as a parameter and invoke this function for each element in the collection. When the function is invoked, the element is passed as the sole argument to the function that forEach took cb => cb(snapshot) is an es6 shorthand function definition.
So in your example, cb is a callback thats then invoked with the snapshot.
Basically, this is the same idea in a forloop
var function1 = (msg) => { alert(msg);}
var function2 = (msg) => { alert(msg.toUpperCase());}
var functions = [function1, function2];
for(var i = 0; i < functions.length; i++){
var fnToApply = functions[i];
fnToApply("hello world");
}
in which an array of functions is invoked in a loop, and each function is designed ahead of time to know what it takes as a param
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
So I have this function which I would like to run:
const normal = () => {
return 'working
}
I can log its output and it works fine:
console.log(normal()) // does output: 'working'
Now I would like to run a function delayed which is exactly the same as normal only it takes 3 seconds before returning
I would like to be able to log this function call but only after 3 seconds, I am understandably logging undefined at the moment and have a feeling that it might be possible to do. Anyway I want the following to happen, the function to hang for 3 seconds, then return data:
console.log(delayed()) // should output: 'working'
My attempts:
const toReturn = () => {
return 'working'
}
const runner = (cb) => {
setTimeout(cb, 1000)
}
export const delayed = () => {
return runner(toReturn)
}
console.log(delayed()) // currently outputting: undefined
undefined is because I am not returning anything from runner, if I return setTimout... in runner, I simply get the whole setTimout function, which is pretty useless.
I know you can simply log after 3 seconds within a callback, but I would like to log what is returned from a setTimeout
When you call console.log (or anything else) it's going to take that action then. JS is not like some languages where you pause code execution.
If you want the console.log to be delayed then you need to delay the actual call to console.log, not the return of the value you're logging.
The simplest way would be something like this:
function delayedLog(seconds)
{
setTimeout(function(){
var val = getSomething(); // <- pretend this returns "later"
console.log(val); // <- after 3 seconds logs "later"
}, seconds*1000);
}
console.log('now');
delayedLog(3);
This question already has answers here:
What do multiple arrow functions mean in JavaScript?
(7 answers)
Closed 6 years ago.
Can anyone explain what the code is doing here
return () => next => action => {
const callAPI = action[CALL_API];
if (typeof callAPI === 'undefined') {
return next(action);
}
let { endpoint } = callAPI;
const { types, bailout } = callAPI;
It is initially returning a function but I don't get why there are two further fat arrows after the first.
If the arrow function has only one parameter, then the parameter around that is optional. You just need to have enough parenthesis to understand them better.
return () => (next) => (action) => {
it returns a function, which when invoked returns another function which accepts one parameter, next. Now when that function is invoked, it returns another function, which accepts another parameter action.
That code can be rewritten like below,
return function() {
return function(next) {
return function(action) {
It seems that the outer function returns a function with parameter next and that returns another one function with parameter action. That code in the link that you given has not minified, but that seems to be obfuscated.