Given code snippet of code does not stop even though I'm using setTimeout in it.
var myObj = {
myFunc: function () {
var self = this;
var timer = setTimeout(function () {
console.log('Timeout called');
self.myFunc();
}, 100);
}
};
myObj.myFunc();
myObj = null;
Inside the setTimeout callback, the given code recursively calling myFunc (self.myFunc()), that's why it is going forever.
Related
This is a Vue class. The method signOut() should fire when the timer ticks. The timer works, except the call signOut().
The problem is with accessing the class method. I'm confused with this, self and access modifiers.
I tried with this.signOut() but it does not work.
How can I call the method signOut?
"use strict";
(async (globals, config, loader, application) => {
const storageLocal = await loader.services.storage.local.getAsync();
class HeaderComponent {
#foo = a;
constructor(tag) {
this.tag = tag;
this.timer();
}
signOut() {
storageLocal.delete('account');
window.location = '/signin.html';
}
timer() {
//document.getElementById("timer"),
var counter = -1;
var timeout;
var startTimer = function timer() {
counter++;
console.log(counter);
signOut(); //<- error can't call class method
timeout = setTimeout(timer, 10000);
};
function resetTimer() {
// here you reset the timer...
clearTimeout(timeout);
counter = -1;
startTimer();
//... and also you could start again some other action
}
document.addEventListener("mousemove", resetTimer);
document.addEventListener("keypress", resetTimer);
startTimer();
}
data() {
return { account: storageLocal.account };
}
}
const component = new HeaderComponent('component-header')
loader.components.set(component.tag, component);
})(window, window.config, window.loader, window.application);
Please note:
signOut() {
storageLocal.delete('account');
window.location = '/signin.html';
}
timer() {
//document.getElementById("timer"),
var counter = -1;
var timeout;
var startTimer = function timer() {
as you can see 'signOut()' is 2 levels below active functions. The logic says it would work like this.parent.signOut() but it DOES NOT !
EDIT3: this.signOut(); will produce
Uncaught TypeError: Cannot read property 'signOut' of undefined
at timer (header.js:30)
at HTMLDocument.resetTimer
The function creates a new context. You need to switch to arrow function and use this.signOut(). Simplified example:
timer() {
var counter = -1;
var timeout;
var startTimer = () => {
counter++;
console.log(counter);
this.signOut();
timeout = setTimeout(startTimer, 1000);
};
setTimeout(startTimer, 1000);
}
Moreover, you have two signOut() methods defined in one class.
You need this and call it like this.signOut()
The startTimer-function does not run in the context of the HeaderComponent's instance.
this in startTimer will point to window when it's executed as a handler in setTimeout.
In order to access the the instance of HeaderComponent, either use an arrow function (as pointed out in an earlier answer. See also Arrow function expressions) which will point this to the outer context (which is HeaderComponent's instance) or define an identifier in timer which points to the instance (eg. const self = this;) and use self instead of this in startTimer.
To apply this to your example (for the sake of consistency, I used var instead of const):
timer() {
var counter = -1;
var timeout;
var self = this;
var startTimer = function() { // Don't use a named function here, it only leads to more confusion
counter++;
console.log(counter);
self.signOut(); // Use `this` of the outer context
timeout = setTimeout(startTimer, 10000); // Use the declared identifier
};
// Rest of the method
}
this is Javascript may be a bit confusing to those who come from different programming languages. If you want to get into more detail, I recommend reading into the MDN reference for this and into Closures
http://jsfiddle.net/hRksW/
function test() {
this.alerting = function () {
alert("test");
};
this.something = function () {
setInterval(function () {
this.alerting();
}, 1000);
};
}
var a = new test();
a.something();
Calling the function something() should call the function alerting() every second. This should alert 'test' every second. Why doesn't that happen and how can I make it happen? Note that I want to keep this design of calling a method in a method, if possible.
Store a reference of this in a variable and use it for method that run outside of the current context (like the setInterval does)
function test() {
var that = this;
this.alerting = function () {
alert("test");
};
this.something = function () {
setInterval(function () {
that.alerting();
}, 1000);
};
}
var a = new test();
a.something();
http://jsfiddle.net/N6hPB/
function test() {
this.alerting = function () {
alert("test");
};
this.something = function () {
setInterval(this.alerting, 1000);
};
}
var a = new test();
a.something();
Hope this helps! Here the timer is in ms.
function something(){
window.setInterval(alerting, 1000);
}
function alerting() {
alert('test');
}
Another way to do it is returning an object instead.
function test() {
var self = {
alerting : function () {
console.log("test");
},
something : function () {
setInterval(function () {
self.alerting();
}, 1000);
}
};
return self;
}
var a = new test();
a.something();
You can do it making an object with functions, and then call them without instantiating it.
var testCaller = {
alerting: function() {
alert("test")
},
something: function() {
// Store current scope
var self = this;
setInterval(function() {
self.alerting();
}, 1000);
}
}
testCaller.something();
You can try this code. I have tested it, and it works. In your code, "this" pointer points to somewhere else.
function test() {
test.prototype.alerting = function() {
alert("alert test");
};
test.prototype.something = function () {
setInterval(this.alerting, 1000);
};
}
var a = new test();
a.something();
i have this example:
var myApp = (function() {
var inputClick = function() {
console.log('inputClick');
};
var loadRecentTimeout = function()
{
window.setTimeout("inputClick()",3000);
};
return {
loadRecentTimeout:loadRecentTimeout,
inputClick:inputClick
};
})();
myApp.loadRecentTimeout(); // this returns inputClick() undefined
window.setTimeout("myApp.inputClick();",3000); // this one seems to work , but it calls that method only one time and not every 3 seconds
can anyone explain how can i make this code call the inputClick() method every 3 seconds?
thanks
You want to call setInterval instead of setTimeout
var eventInterval = window.setInterval(function () {
myApp.inputClick();
},3000);
You also should pass your function as a function instead of a string.
If you need to cancel your repeating event you can call clearInterval
clearInterval(eventInterval)
When you use a string "functionName()" it evals it in window scope. Instead, assign a reference to the function with just using the name. setTimeout only fires once, you want to use a setInterval.
var myApp = (function() {
var inputClick = function() {
console.log('inputClick');
};
var loadRecentTimeout = function()
{
window.setInterval(inputClick,3000);
};
return {
loadRecentTimeout:loadRecentTimeout,
inputClick:inputClick
};
})();
I have this Javascript class:
function PageManager () {
this.timeoutHandler = function () {
alert ("hello");
}
this.startTimeout = function () {
this.timeout = setTimeout ("this.timeoutHandler()", 1000);
}
}
When I call obj.startTimeout (); I get this error:
this.timeoutHandler is not a function
How do I call a class function in the timeout?
If you pass a string to setTimeout, the code is evaluated in the global scope. Always pass a function reference:
this.startTimeout = function () {
var self = this;
this.timeout = setTimeout(function() {
self.timeoutHandler();
}, 1000);
}
Or if you don't need a reference to the object inside timeoutHandler, then you can pass the function directly:
this.timeout = setTimeout(this.timeoutHandler, 1000);
The problem is that you're passing setTimeout a string. This string is eval'd, with a scope of the window. So if you were to do this:
this.timeout = setTimeout ("console.log(this);", 1000);
... with Firebug installed, you'd see that this is window, which does not have a timeoutHandler method, of course.
This is why you should never, ever pass setTimeout a string. Give it a function reference instead.
function PageManager () {
this.timeoutHandler = function () {
alert ("hello");
console.log(this);
}
this.startTimeout = function () {
this.timeout = setTimeout (this.timeoutHandler, 1000);
}
}
obj = new PageManager ();
obj.startTimeout();
When you execute this code, you'll have the scope you're expecing.
Please, someone can explain me what is the meaning of (this) at the end of the function in a setInterval :
function Klass(name) {
this.name = name;
this.handle = null;
this.startTimer = function() {
this.handle = setInterval(function(obj) {
return(function() {
alert(obj.name);
});
}(this), 5000); // <-------------------- (this)
}
The use of this in the construct is intended to preserve the meaning of this at the point setInterval is called for the actual call back that is executed at the given interval. Without the manual preservation this would become the owner of the function at the point setInterval was called.
Here's a very nice article on this subject
http://www.quirksmode.org/js/this.html
Another way this could be done which may be a bit clearer is the following
var self = this
this.handle = setInterval(function() { alert(self.Name); }, 5000);