How to run setTimeOut once in repeatedly running function? - javascript

function setPositionFromEngine is running multiple times. I need to run setTimeout once in this function and then start anotherFunction after set timeout is done
setPositionFromEngine(pos) {
setTimeout(() => {
this.setPos(pos);
}, 2000);
anotherFunction() {...}
}

If anotherFunction needs to run after the specified timeout then move it inside of setTimeout. Then if you need to ensure that setTimeout only runs once, you need to add a condition, such as:
// Somewhere outside of setPositionFromEngine
var didSetPosition = false;
setPositionFromEngine (pos) {
if (!didSetPosition) {
setTimeout(() => {
this.setPos(pos);
didSetPosition = true; // <-- This is key
anotherFunction();
}, 2000);
}
}

Related

Execute setInterval function without delay first time, but conditionally more times after delay

In my React Native app, I'm using setInterval to poll an API call every few seconds to achieve a certain goal, like this:
this.timer = setInterval(() => this.doSomething(), 4000);
The problem is it only starts after 4 seconds. I have read other answers that suggest calling the function immediately and then calling setInterval to execute it again after a delay, but that is not working for me because what if the first call succeeds in achieving what I needed it to do? Then I don't want it to be called again, only once would have been enough.
How do I call it once, then if it fails I start polling it every 4 seconds?
Edit: Forgot to mention specifically that this.doSomething is an async function.
Execute the function first and then setInterval if it fails. You just need to return from the function whether it succeeded, and add an if statement before using setInterval.
let timer;
function doSomething() {
if (Math.random() > 0.5) {
// if success, return true
console.log("Success")
if (timer) clearInterval(timer);
return true;
} else {
// if failed, return false
console.log("Failed")
return false;
}
}
let result = doSomething()
if (!result) {
timer = setInterval(doSomething, 1000);
}
Async version:
let timer;
async function doSomething() {
if (Math.random() > 0.5) {
// if success, return true
console.log("Success")
if (timer) clearInterval(timer);
return true;
} else {
// if failed, return false
console.log("Failed")
return false;
}
}
doSomething().then(
(result) => {
if (!result) {
timer = setInterval(doSomething, 1000);
}
}
)

Stop custom setInterval() function similar to clearInterval() using return variable

I have a custom setInterval function that can modify the interval as it runs. I would like to be able to return a variable that the caller can modify later on. Similar to how clearInterval() works.
Custom Set Interval Function
customSetInterval(callback, interval) {
let stop = false;
this.startInterval(callback, interval, stop);
return stop;
}
startInterval(callback, interval, stop) {
if (stop) {
return;
}
setTimeout(() => {
callback();
interval += 100;
this.startInterval(callback, interval, stop);
}, interval);
}
My current implementation doesn't work because I'm simply returning the value. Not the variable itself. Is it possible to do something like this in JS?
Example Execution
let stop = this.devicewise.customSetInterval(() => {
console.log('HELLO!');
}, 1000);
setTimeout(() => {
console.log('stopping!');
stop = true;
}, 5000);
If this is not possible I plan on creating a boolean hashmap that I add to every time I start. Then create a customClearInterval function to modify that hashmap.
Seems like you wanted a one-time execution with the callback, maybe something like that:
class CustomInterval {
constructor() {
this.id = -1;
}
start(callback, interval) {
console.log(`executing callback in ${interval}ms`);
this.id = setTimeout(() => {
callback();
console.log('callback fired');
}, interval);
}
stop() {
clearTimeout(this.id);
console.log('stopped');
}
}
// ...
let j = new CustomInterval();
j.start(() => {
// do stuff here
}, 5000);
// after some other operations, you decided to cancel the above delayed execution
// no problem.
j.stop();

How to properly scope function to run on delay in Polymer?

I am trying to add the input data into an array delayed for 2 seconds after the last keystroke. However, when I run this I get the following error: Uncaught TypeError: this._validateInput is not a function
How can I properly scope this._validateInput() to run on delay?
I tried let func = this._validateInput();, but that seems to run the function every time that func is set.
Also, the on-change input handler only fires when the input loses focus.
Looking for away to solve this...
<paper-input id="itemId" on-input="_autoAddToArray"></paper-input>
...
_validateInput () {
console.log('validate input');
}
_autoAddToArray () {
let timeout = null;
clearTimeout(timeout);
timeout = setTimeout(function () {
this._validateInput();
}, 2000);
}
Either use a lambda:
setTimeout(
() => this._validateInput(),
2000
);
or bind the function
setTimeout(this._validateInput.bind(this), 2000);
Either solution should work
The lambda works because it doesn't have its own scope.
The binding works because it applies the scope "before" running it so to speak
The this keyword always refers to the this of the current scope, which changes any time you wrap something in function() { ... }
You need to assign your this in the outer scope to a variable.
var self = this;
timeout = setTimeout(function () {
self._validateInput();
}, 2000);
Reference: setTimeout scope issue
<paper-input id="itemId" on-input="_autoAddToArray"></paper-input>
...
_autoAddToArray () {
let timeout = null;
clearTimeout(timeout);
let that = this;
timeout = setTimeout(function () {
that._validateInput();
}, 2000);
}
_validateInput () {
if(this.$.itemId.value) {
// do something
}
}

How to abort function by timeout at JavaScript

I need to execute some function but if timeout expired I need to abort this function. I tried to use setTimeout and setImmediate. I wrote this example and used setInterval in callback for checking of working but it did't help me:
function waiter(timeout, fun) {
var functionHandler = setImmediate(fun);
var timeoutHandler = setTimeout(() => {
console.log('stoped');
clearImmediate(functionHandler);
clearTimeout(timeoutHandler);
}, timeout);
fun();
}
waiter(5000, () => {
setInterval(() => {
console.log('work');
}, 500);
});
After clearImmediate and clearTimeout my interval still working. How I understood that method doesn't guarantee that my function will be aborted.
Does anybody have an idea how to abort function execution?
UPDATE:
Yes, I know that I should call clearInterval but it's just an example for work checking. For example I should parse some big data and if it doesn't can do it by timeout I need to cancel this function execution and call something else.
The clearXXX functions don't abort functions that are currently running, they just remove functions from the async queue, so that they never start to run. JavaScript always executes code to its completion. You cannot interrupt code that's running in the main thread.
You need to name your interval
and clear it by its name. So your interval is no longer anonymous, but you've got a reference for it.
let counter = 10;
let newYearCountdown = setInterval( () => {
console.log(counter);
counter--
if (counter === 0) {
console.log("HAPPY NEW YEAR!!");
// here i clear interval by its name.
clearInterval(newYearCountdown);
}
}, 1000);

setInterval fires Ajax call twice every time

I have the following JS code:
var delay = 5000;
function init() {
setInterval(getFileCount, delay);
}
function getFileCount() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
// Do stuff with response
});
}
On page load I'm calling the init() function. The idea is to start the interval and call the getFileCount() function every 5 seconds.
So, the interval waits 5s after the page loads and runs, but it always makes the Ajax call twice.
What am I missing?
UPDATE:
I know the init() function is triggered twice on page load (thanks to the comment by Yury Tarabanko). I don't quite understand, why. The almost-full code:
$(function() {
'use strict';
function handleCourseNotification() {
var delay = 5000;
function init() {
setInterval(getFileCount, delay);
}
function getFileCount() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
updateCourseList(response.items);
});
}
function updateCourseList(items) {
// update course list...
}
return {
init: init
};
}
if ($('#js-auth-course-list').length) {
var notificationHandler = handleCourseNotification();
notificationHandler.init();
}
});
It's a small module, which I initialize after page load, if a specific element is available in the DOM - $('#js-auth-course-list'). Why is init called 2 times actually? I directly call it once.
In general, it is not a good idea to call asynchronous calls inside a setInterval() because you do not know the exact response time. So, you could end up calling the second async function before the response from the first call has returned.
You can try with setTimeout() like this:
var delay = 5000;
var async = function() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
// Do stuff with response
// Call the async function again
setTimeout(function() {
async();
}, delay);
});
}
async();

Categories