How to execute code not from string using function? - javascript

How would I execute code not from a string? Here is an example:
var ready = false;
executeWhen(ready == true, function() {
console.log("hello");
});
function executeWhen(statement, code) {
if (statement) {
window.setTimeout(executeWhen(statement, code), 100);
} else {
/* execute 'code' here */
}
}
setTimeout(function(){ready = true}, 1000);
Could I use eval();? I don't think so, I think that's only for strings.

You call it with code().
You need to change statement to a function as well, so it will get a different value each time you test it.
And when you call executeWhen() in the setTimeout(), you have to pass a function, not call it immediately, which causes infinite recursion.
var ready = false;
executeWhen(() => ready == true, () =>
console.log("hello"));
function executeWhen(statement, code) {
if (!statement()) {
window.setTimeout(() => executeWhen(statement, code), 100);
} else {
code();
}
}
setTimeout(function() {
ready = true
}, 1000);

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();

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();

How to return value from an extended casperjs function?

I am trying to return a value from the below function like so.
html = casper.get_HTML(myselector);
All I am getting returned is "undefined" (return_html). However, the 'html' variable is getting set properly. The over all function works properly. It's just the return value that is the issue.
How do you do it?
casper.get_HTML = function(myselector) {
var return_html;
casper.waitForSelector(myselector,
function() {
var html = casper.getHTML(myselector, false);
return_html = html; //got the html
},
function() { // Do this on timeout
return_html = null;
},
10000 // wait 10 secs
);
return return_html;
};
In CasperJS all then* and all wait* functions are step functions which are asynchronous. It means that you cannot return something that is determined asynchronously in your custom function. You have to use a callback:
casper.get_HTML = function(myselector, callback) {
this.waitForSelector(myselector,
function then() {
var html = this.getHTML(myselector, false);
callback(html);
},
function onTimeout() {
callback();
},
10000 // wait 10 secs
);
return this; // return this so that you can chain the calls
};
casper.start(url).get_HTML("#myid", function(html){
if (html) {
this.echo("success");
} else {
this.echo("failed");
}
}).run();

SetTimeout Executing faster then assigned interval

I have assigned 5000 ms to Settimeout but it is executing before assigned time interval.Can any body explain why it is happening.
<script type="text/javascript">
var getcallback = {
closure: function (callback, functionparam) {
return callback.call(functionparam);
}
}
var cleartimeout;
var startSlideShow = {
timerid: 5000,
startAnimation: function () {
cleartimeout = setTimeout(getcallback.closure(function () {
alert("this is a basic example of chaining methods");
this.startAnimation();
},this), this.timerid);
},
stopAnimation:function(){
}
}
startSlideShow.startAnimation();
</script>
Because getcallback.closure() is executing the function right away, you are not storing a reference to a function to call at a later time.
As soon as you call startAnimation, you're calling getcallback.closure, which immediately calls the callback function. To use setTimeout correctly, you need to either have closure return a function, or not use such a strange thing, and instead just use an anonymous function.
Something along the lines of:
var getcallback = {
closure: function (callback, functionparam) {
return function() {
callback.call(functionparam);
};
}
}
...
Or, to be cleaner, just:
var cleartimeout;
var startSlideShow = {
timerid: 5000,
startAnimation: function () {
cleartimeout = setTimeout(function () {
alert("this is a basic example of chaining methods");
this.startAnimation();
}, this.timerid);
},
stopAnimation:function(){
}
}
startSlideShow.startAnimation();

Categories