JavaScript Setinterval and 'This' Solution

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



Leave a reply



Submit