Execute a function BEFORE ANY function is executed - javascript

What I want to do is to execute a function automatically every time BEFORE ANY function is executed in JS, regardless if it's a custom or native function if possible.
ie.
whatIWant(functionName){
return console.log('called before '+functionName);
}
function blah(){
return console.log('called blah');
}
function meh(){
return console.log('called meh');
}
alert('woot');
blah();
//will output :
//called before blah
//called blah
meh();
//will output :
//called before meh
//called meh
alert();
//will output :
//called before alert
//will pop up dialog: woot
I do not want to do the following:
Function.prototype.onBefore = function(){};
blah.onBefore();
is it even possible to do what I am asking for? any suggestions, read, or w/e?
Thanks in advance.

What about just providing your function as a callback to whatIWant like this:
function whatIWant(fn) {
var fnName = fn.toString();
fnName = fnName.substr('function '.length);
fnName = fnName.substr(0, fnName.indexOf('('));
console.log('called before ' + fnName);
fn();
}
function meh() {
console.log('called meh');
}
function blah() {
console.log('called blah');
}
whatIWant(meh);
whatIWant(blah);
whatIWant(alert)

what do you guys think about this solution? :)
function bleh(){
console.log('exe a');
}
function limitFn(fn,n) {
var limit = n ;
var counter = 1 ;
var fnName = fn.toString();
fnName = fnName.substr('function '.length);
fnName = fnName.substr(0, fnName.indexOf('('));
return function(){
if(counter <= limit) {
console.log(counter + ' call before ' + fnName + ' limit ' + limit);
counter++;
fn();
} else {
console.log('limit of ' + limit + ' exes reached') ;
}
};
}
limited = limitFn(bleh,2);
limited();
limited();
limited();
limited();

Related

Change value from outside of the function

I have something like the following:
function somefunc() {
function anotherfunc() {
...
if ( m > ...
...
}
$(window).on("scroll", anotherfunc);
}
somefunc();
I want to be able to change m value in execution of somefunc("value") (last step in above code snippet - somefunc();), so it would transfer the m value to the anotherfunc - but I don't know if I can(able) do so and would like to ask some for your help.
function somefunc(m) {
function anotherfunc() {
console.log(m)
}
$(window).on("scroll", function(){
anotherfunc(m);
});
}
somefunc(1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Like commented, declare m outside the functions:
var m = 1;
console.log('Outside functions: ' + m);
function someFunc() {
m += 1;
console.log('someFunc: ' + m);
function otherFunc() {
m += 1;
console.log('otherFunc: ' + m);
}
otherFunc();
}
someFunc();

Stop function from re- executing for one second with settimeout

I want to prevent my function from re-executing for one second after it's last executed. I've tried the method below, but it doesn't work.
function displayOut() {
// images
document.getElementById("imgBox").style.backgroundImage = "url(" + db.rooms[roomLoc].roomImg + ")";
// Diologue box
diologueBox.innerHTML = ""; // Clear Box
teleTyperDiologue(db.rooms[roomLoc].description +
" The room contains: " +
(function() {
let x = "";
for (let i = 0; i < db.items.length; i++) {
if (db.items[i].location === roomLoc && db.items[i].hidden === false) {
x += db.items[i].name + ", "
}
}
x = x.slice(0, x.length -2);
if (x === "") {
x = " nothing of special interest";
}
return x;
})()
+ ".");
pause();
};
function pause() {
setTimeout(function() {
// Wait one second!
}, 1000);
}
You could use a pattern like this:
var executing = false;
function myFunc() {
if(!executing) {
executing = true;
//Code
console.log('Executed!');
//End code
setTimeout(function() {
executing = false;
}, 1000);
}
}
setInterval(myFunc, 100);
So in your case, this would look like this:
var executing = false;
function displayOut() {
if(!executing) {
executing = true;
// images
document.getElementById("imgBox").style.backgroundImage = "url(" + db.rooms[roomLoc].roomImg + ")";
// Diologue box
diologueBox.innerHTML = ""; // Clear Box
teleTyperDiologue(db.rooms[roomLoc].description +
" The room contains: " +
(function() {
let x = "";
for (let i = 0; i < db.items.length; i++) {
if (db.items[i].location === roomLoc && db.items[i].hidden === false) {
x += db.items[i].name + ", "
}
}
x = x.slice(0, x.length -2);
if (x === "") {
x = " nothing of special interest";
}
return x;
})()
+ ".");
setTimeout(function() {
executing = false;
}, 1000);
}
};
Try to use throttle (http://underscorejs.org/#throttle) or debounce (http://underscorejs.org/#debounce) from underscore, one of those should fit your needs
This one will achieve that:
function run () {
console.log('Im running');
pause(1000);
};
function pause(s) {
console.log('Im paused');
setTimeout(() =>{
run();
}, s)
};
run();
The code above will run every 1 sec but if you want to make sure the function cant be runned again until you decide then you could use a flag instead like:
let canExecute = true;
function run () {
if (canExecute) {
console.log('Im running');
canExecute = false;
pause(1000);
}
};
function pause(s) {
console.log('Im paused');
setTimeout(() =>{
canExecute = true;
}, s)
};
run();
run();
run();
setTimeout(() =>{
run();
}, 2000)
This code will execute run function twice, first on time and then one more after 2 sec.

Javascript context within a function

I am binding a function to an event.
$('div.my_div').bind("mouseenter", timerFunc);
The problem that I have is that my context changes and I cannot access my elements. I must admit that javascript context is terribly confusing to me:
function timerFunc() {
//alert('Square ' + $(this).attr('data-somevalue') + ' named function called!');
var count_to = 10;
var count = 0;
var countup = setInterval(function () {
count++;
$(this).find('.countup').html(count + ' seconds!'); // <-- trying to access THIS square
//self.find('.countup').html(count + ' seconds!'); // <-- trying to access THIS square
if (count == count_to) {
count = 0;
}
}, 750);
}
Please help
Store $(this) in a variable and use it in your nested function:
function timerFunc() {
//alert('Square ' + $(this).attr('data-somevalue') + ' named function called!');
var elem = $(this);//$(this) is stored in elem variable
var count_to = 10;
var count = 0;
var countup = setInterval(function () {
count++;
//so you can use it here in nested function
elem.find('.countup').html(count + ' seconds!'); // <-- trying to access THIS square
//self.find('.countup').html(count + ' seconds!'); // <-- trying to access THIS square
if (count == count_to) {
count = 0;
}
}, 750);
}
setInterval executes in global context that is window, so this is window. So cache the variable and use it instead
var that = this;
var countup = setInterval(function () {
count++;
$(that).find('.countup').html(count + ' seconds!');
if(count == count_to) {
count = 0;
}
}, 750);

Return value inside a setInterval

I want to return a value inside a setInterval. I just want to execute something with time interval and here's what I've tried:
function git(limit) {
var i = 0;
var git = setInterval(function () {
console.log(i);
if (i === limit - 1) {
clearInterval(git);
return 'done';
}
i++;
}, 800);
}
var x = git(5);
console.log(x);
And it's not working.
Is there any other way?
What I'm going to do with this is to do an animation for specific time interval. Then when i reached the limit (ex. 5x blink by $().fadeOut().fadeIn()), I want to return a value.
This is the application:
function func_a(limit) {
var i = 0;
var defer = $.Deferred();
var x = setInterval(function () {
$('#output').append('A Running Function ' + i + '<br />');
if (i == limit) {
$('#output').append('A Done Function A:' + i + '<br /><br />');
clearInterval(x);
defer.resolve('B');
}
i++;
}, 500);
return defer;
}
function func_b(limit) {
var c = 0;
var defer = $.Deferred();
var y = setInterval(function () {
$('#output').append('B Running Function ' + c + '<br />');
if (c == limit) {
$('#output').append('B Done Function B:' + c + '<br /><br />');
clearInterval(y);
defer.resolve('A');
}
c++;
}, 500);
return defer;
}
func_a(3).then( func_b(5) ).then( func_a(2) );
This is not functioning well, it should print A,A,A,Done A,B,B,B,B,B,Done B,A,A,Done A but here it is scrambled and seems the defer runs all function not one after the other but simultaneously. That's why I asked this question because I want to return return defer; inside my if...
if (i == limit) {
$('#output').append('A Done Function A:' + i + '<br /><br />');
clearInterval(x);
defer.resolve('B');
// planning to put return here instead below but this is not working
return defer;
}
Do you expect it to wait until the interval ends? That would be a real pain for the runtime, you would block the whole page. Lots of thing in JS are asynchronous these days so you have to use callback, promise or something like that:
function git(limit, callback) {
var i = 0;
var git = setInterval(function () {
console.log(i);
if (i === limit - 1) {
clearInterval(git);
callback('done');
}
i++;
}, 800);
}
git(5, function (x) {
console.log(x);
});
Using a promise it would look like this:
function git(limit, callback) {
var i = 0;
return new Promise(function (resolve) {
var git = setInterval(function () {
console.log(i);
if (i === limit - 1) {
clearInterval(git);
resolve('done');
}
i++;
}, 800);
});
}
git(5)
.then(function (x) {
console.log(x);
return new Promise(function (resolve) {
setTimeout(function () { resolve("hello"); }, 1000);
});
})
.then(function (y) {
console.log(y); // "hello" after 1000 milliseconds
});
Edit: Added pseudo-example for promise creation
Edit 2: Using two promises
Edit 3: Fix promise.resolve
Try to get a callback to your git function.
function git(limit,callback) {
var i = 0;
var git = setInterval(function () {
console.log(i);
if (i === limit - 1) {
clearInterval(git);
callback('done') // now call the callback function with 'done'
}
i++;
}, 800);
}
var x = git(5,console.log); // you passed the function you want to execute in second paramenter

JS Execute functions in order, while passing the next function as an argument

I am trying to eliminate the "callback pyramid of DOOM" by doing this:
$$( //my function
function(next) { // <- next is the next function
setTimeout(next,1000); // simple async function
},
function(next){ // this function is the previous's function "next" argument
waitForSomethingAndReturnAValue(next, "I am a parameter!");
},
function(aValue){
console.log("My value is:" + aValue);
}
);
BUT I have been fiddling for about an hour, and my code doesn't work, any help? this is what I got so far:
function $$(){
for (a in arguments){
arguments[a] = function(){
arguments[a](arguments[Math.max(-1, Math.min(a+1, arguments.length-1))]);
};
}
arguments[0]();
}
Something like this works:
function $$() {
if (arguments.length <= 0) return;
var args = Array.prototype.slice.call(arguments); // convert to array
arguments[0](function () { $$.apply(null, args.slice(1)); });
}
$$(function(next) { alert("one"); next() }, function (next) { alert("two"); next() });
http://jsfiddle.net/Cz92w/
You can try this:
function $$(){
var i=0, ret, args = [].slice.call(arguments);
var obj = {
next: function() {
ret = args[i++].call(obj, ret);
}
};
obj.next();
}
and use it like this:
$$(
function() {
console.log(Date() + ' - Function 1');
setTimeout(this.next, 1e3); // simple async function
},
function(){
console.log(Date() + ' - Function 2');
return waitForSomethingAndReturnAValue(this.next, "I am a parameter!");
},
function(aValue){
console.log(Date() + ' - Function 3');
console.log("My value is:" + aValue);
}
);
function waitForSomethingAndReturnAValue(callback, param) {
setTimeout(callback, 2e3);
return param + param;
}
Basically, the returned value in each function is passed as the argument to the next one. And the reference to the next function is this.next.

Categories