JavaScript setInterval and `this` solution
The setInterval line should look like this:-
this.intervalID = setInterval(
(function(self) { //Self-executing func which takes 'this' as self
return function() { //Return a function in the context of 'self'
self.retrieve_rate(); //Thing you wanted to run as non-window 'this'
}
})(this),
this.INTERVAL //normal interval, 'this' scope not impacted here.
);
Edit: The same principle applies to the " onload
". In this case its common for the "outer" code to do little, it just sets up the request an then sends it. In this case the extra overhead an additinal function as in the above code is unnecessary. Your retrieve_rate should look more like this:-
retrieve_rate : function()
{
var self = this;
var ajax = new XMLHttpRequest();
ajax.open('GET', 'http://xyz.example', true);
ajax.onreadystatechanged= function()
{
if (ajax.readyState == 4 && ajax.status == 200)
{
// prefs available as self.prefs
}
}
ajax.send(null);
}
How to pass this to window setInterval
Store a reference to this
:
function a() {
var self = this;
self.b = 1;
self.set = setInterval(function() {console.log(self.b);}, 200);
}
The anonymous function that you pass to setInterval
has access to any variables in its containing scope, i.e., any local variables of function a()
. The magic of JS closures keeps these variables alive even after a()
has completed, and each invocation of a()
gets its own closure.
Is there a better solution than setInterval when I need the interval to be very precise over time?
It probably would be a better idea to calculate everything in absolute time. So have a var starttime = Date.now();
, and then calculate where every note should be var expected_note_time = starttime+beat_interval*beat_number
. You can then add a listener on keypress and then log the exact time the keypress was hit. If abs(time_pressed-expected_note_time) < ALLOWED_MISTAKE_VARIANCE
, then add that point to the user's score. Good luck.
setInterval with (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);
setInterval will become unreliable and inaccurate sometimes
setTimeout and setInterval in javascript only promise that they won't be run before the specific time. they try to execute your function as soon as possible but they sometimes can't do that. They are not timers. They are some functions that call a callback after a time which is the minimum amount of waiting before calling the callback function. Unfortunately there is not an accurate timer in javascript. you can implement it yourself.
Edit: you may ask how:
read the following thread:
https://stackoverflow.com/a/29972322/12337783
Referencing this inside setInterval/setTimeout within object prototype methods
Unlike in a language like Python, a Javascript method forgets it is a method after you extract it and pass it somewhere else. You can either
Wrap the method call inside an anonymous function
This way, accessing the baz
property and calling it happen at the same time, which is necessary for the this
to be set correctly inside the method call.
You will need to save the this
from the outer function in a helper variable, since the inner function will refer to a different this
object.
var that = this;
setInterval(function(){
return that.baz();
}, 1000);
Wrap the method call inside a fat arrow function
In Javascript implementations that implement the arrow functions feature, it is possible to write the above solution in a more concise manner by using the fat arrow syntax:
setInterval( () => this.baz(), 1000 );
Fat arrow anonymous functions preserve the this
from the surrounding function so there is no need to use the var that = this
trick. To see if you can use this feature, consult a compatibility table like this one.
Use a binding function
A final alternative is to use a function such as Function.prototype.bind or an equivalent from your favorite Javascript library.
setInterval( this.baz.bind(this), 1000 );
//dojo toolkit example:
setInterval( dojo.hitch(this, 'baz'), 100);
Javascript setInterval doesn't work with this. objects
You need to bind the setInterval to the same target as your class.
this.moveUp = function ()
{
setInterval(function ()
{
this.yPos--;
this.domObj.style.top = (this.yPos * multiplicator) + 'px';
}.bind(this), 1000);
}
Nodejs setInterval and run first immediatly not after interval
For modern JavaScript await
and async
should be used instead of then
and catch
.
This will make many things easier, and the code becomes more readable. You e.g. can use a regular for
loop to iterate over an array while executing asynchronous tasks within it. And use try-catch
blocks in the same way as you would in synchronous code.
// a helperfunction that creates a Promise that resolves after
// x milliseconds
function wait(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
async function rollDice(profilearray, browserarray, url) {
for (let i = 0; i < profilearray.length; i++) {
// depending how you want to handle the wait you would create
// the "wait"-Promise here
// let timer = wait(3000)
let testcafe = await createTestCafe("localhost", 1337, 1338, void 0, true);
try {
let runner = testcafe.createRunner();
inputStore.metaUrl = url;
inputStore.metaLogin = teamdataarray[0].email;
inputStore.metaPassword = teamdataarray[0].password;
inputStore.moderator = profilearray[i].profil;
inputStore.message = profilearray[i].template;
inputStore.channelid = profilearray[i].channelid;
let failedCount = await runner.src([__basedir + "/tests/temp.js"])
.browsers(browserarray)
.screenshots("", false)
.run()
if (failedCount > 0) {
// ...
} else {
// ...
}
} catch (err) {
console.log(profilearray[i].profil);
console.log("Testcafe Error" + error);
} finally {
testcafe.close();
}
// Here you would wait for the "wait"-Promise to resolve:
// await timer;
// This would have similar behavior to an interval.
// Or you wait here for a certain amount of time.
// The difference is whether you want that the time the
// runner requires to run counts to the waiting time or not.
await wait(3000)
}
return "Fertig"
}
Related Topics
How to Fire and Forget a Promise in Nodejs (Es7)
Determining Image File Size + Dimensions via JavaScript
Es6 Modules: Export Single Class of Static Methods or Multiple Individual Methods
How to Display Length of Filtered Ng-Repeat Data
Convert String with Commas to Array
How to Check File Input Size with Jquery
Where Do You Include the Jquery Library From? Google JSAPI? CDN
Check Whether Variable Is Number or String in JavaScript
React - Uncaught Typeerror: Cannot Read Property 'Setstate' of Undefined
Jquery.Parsejson Throws "Invalid JSON" Error Due to Escaped Single Quote in JSON
What's Wrong with Awaiting a Promise Chain
React Native - Image Require Module Using Dynamic Names
Why Does JavaScript Handle the Plus and Minus Operators Between Strings and Numbers Differently
How to Format Time Since Xxx E.G. "4 Minutes Ago" Similar to Stack Exchange Sites
Jquery - Setting the Selected Value of a Select Control via Its Text Description
Convert Utc Epoch to Local Date
Add Directives from Directive in Angularjs
Window.Location.Href and Window.Open () Methods in JavaScript