print in console all the function which is being executed in javascript - javascript

I am creating AngularJS Javascript application in which i have 500/600 function in a single Directive,
Many functions are Inter connected with each other,
flow starts from the On load Event,
I want to know when i run the project,
which functions are being called on Onload Event
and i want to print the same on console,
I google it but i am not able to get anything,
is there any way to find out the functions which is being executed?

Call console.trace('calling on-load') to find stack-trace on on-load function. It would be better to call trace on the last function you expect to be executed to find all other function which has been called before.

You can wrap all your functions into "log wrapper":
var self = this;
function LogWrapper(action){
return function(){
console.log(action.name);
return action.apply(self, arguments);
}
}
//usage:
function ActualFunctionInner(arg1, arg2){
//some logic
}
var ActualFunction = LogWrapper(ActualFunctionInner);
var result = ActualFunction(1, 2);//console: ActualFunctionInner
Second solution is via Proxy:
let handler = {
get(target, propKey) {
var inner = target[propKey];
return function () {
console.log(inner.name);
return inner.apply(this, arguments);
};
}
};
var loggedSelf = new Proxy(self, handler);
var result = loggedSelf.ActualFunction(1, 2);//console: ActualFunction

Related

Calling a nested function present inside JQuery declaration

I have a function called "destination" nested in scrip1.js file. If I add this file at the end of webpage using , how can I trigger it at the next step? Here are some contents of script1.js.
script1.js
$.something = function(element, options) {
function start() {
function destination(arg1, arg2..) {
$.notify(some args);
}
}
$("body").on("click", ".notify-btn", function (event) {
event.preventDefault();
destination(some args);
});
someOtherFunction();
start();
}
$.fn.something = function (options) {
return this.each(function () {
if (undefined == $(this).data("something")) {
var plugin = new $.something(this, options);
$(this).data("something", plugin);
}
});
};
I tried this, but is not working. Chrome console is showing error about this function.
<script type="text/javascript" src="script1.js"></script>
<script>
$.fn.something().destination();
</script>
I can not change this script1.js, so any possible way?
There's no specific connection between variables declared during function execution - and how the rest of the world sees the result of execution. So this code:
function start() {
function destination(arg1, arg2..) {
$.notify(some args);
}
}
start();
... lets destination value (remember, functions in JS are first-class citizens) go away when start() completes its execution. That's actually quite convenient if you want to encapsulate some implementation details and hide it from users; this technique (also known as Module pattern) was often used in pre-class world to implement private properties in vanilla JavaScript.
However, all the values returned from a function can be reused. For example, here...
$.something = function(element, options) {
function start() {
function destination(arg1, arg2..) {
$.notify(some args);
}
return {
destination
};
}
return start();
}
... you make destination function a part of object that is returned from start(). Now $.something returns an object, too; that means it can be reused:
var plugin = new $.something(this, options);
// ...
plugin.destination('some', 'args');
If you're afraid changing the return value might hurt someone, you can try to assign value of destination to $.something object itself as its property, like this:
$.something = function(element, options) {
function start() {
function destination(arg1, arg2..) {
$.notify(some args);
}
return destination;
}
// ...
const destination = start();
$.something.destination = destination;
}
The returned value is not modified, yet function is accessible. Still, that's not actually a good workaround; the biggest issue is that any subsequent calls on $.something will rewrite the value of that function, which might be not a good thing if its execution depends on some scoped variables.
While technically there's a way to fetch destination function code by parsing $.something source code, I really doubt it's worth the effort in your case.

setInterval in member function of object error

I'm trying to create a throttling queue of sorts in a nodeJS module. I'm getting this error back:
timers.js:265
callback.apply(this, args);
^
TypeError: Cannot read property 'apply' of undefined
at wrapper [as _onTimeout] (timers.js:265:13)
at Timer.listOnTimeout (timers.js:110:15)
I'm guessing that I'm doing something stupid, as usual, but is there a reason that it loses the closure scope or something when the second interval runs?
var queueSvc = function(settings){
var queue = ['bob', 'is', 'name', 'my', 'hi'];
var svc = {};
var runtime;
svc.addQuery = function(queueEntry){
queue.push(queueEntry);
};
svc.stopQueue = function(){
clearInterval(runtime);
};
svc.startQueue = function(){
runtime = setInterval(runQueue(queue), settings.queueInterval);
};
svc.emptyQueue = function(){
//This method of emptying the array needs to change
//if we decide to make the queue a public property
queue = [];
};
return svc;
};
function runQueue(queue){
console.log(JSON.stringify(queue));
if(queue.length > 0){
var entry = queue.pop();
console.log(entry);
}
}
var it = queueSvc({queueInterval: 3000});
it.startQueue();
This is a very common mistake. You are running runQueue(queue) immediately and then passing the return value of that to setInterval(). That return value is undefined so what you are doing is essentially this:
runQueue(queue);
setInterval(undefined, settings.queueInterval);
This is obviously, not what you want. Whenever you put () after a function as in runQueue() that means to run it immediately. A function name or definition without () after it is just passing a function reference that can be called later.
So, you need to pass a function reference to setInterval() that can be called LATER like this:
setInterval(function() {
runQueue(queue);
}, settings.queueInteval);
Sometimes people understand it a bit better when you break it out into a named function (not necessary, but helpful in understanding what is going on):
function run() {
runQueue(queue);
}
setInterval(run, settings.queueInteval);
Here you see you are passing only a function reference to setInterval() and letting the timer infrastructure call the function some time later.
The anonymous function in my first code block accomplishes the same thing. It declares a second function that we can pass a reference of to setInterval() and when that is called, it then calls runQueue(queue) with the desired argument.
This line looks very suspcious:
setInterval(runQueue(queue), settings.queueInterval);
runQueue doesn't return a function, in fact it returns nothing (undefined). You probably want:
setInterval(function () {
runQueue(queue);
}, settings.queueInterval);
To supplement existing answers, wrapping runQueue into something callable works. However, you could also restructure your logic entirely.
var queueSvc = function(settings){
var queue = ['bob', 'is', 'name', 'my', 'hi'];
var svc = {};
var runtime;
svc.addQuery = function(queueEntry){
queue.push(queueEntry);
};
svc.stopQueue = function(){
clearInterval(runtime);
};
svc.startQueue = function(){
runtime = setInterval(svc.runQueue, settings.queueInterval);
};
svc.emptyQueue = function(){
//This method of emptying the array needs to change
//if we decide to make the queue a public property
queue = [];
};
svc.runQueue = function() {
console.log(JSON.stringify(queue));
if(queue.length > 0){
var entry = queue.pop();
console.log(entry);
}
};
return svc;
};
var it = queueSvc({queueInterval: 3000});
it.startQueue();
This is exactly what I was looking for, thanks.
Only one issue: you implemented a stack, not a queue.
Queues are FIFO and use push() and shift()
Stacks are LIFO and use push() and pop()
As long as the ordering does not matter, then either is fine.

js execute function after object is defined

I need for a function to be executable only after an object is defined, I'm currently working in a fascade pattern and one method is dependent on another method. in this case 'addNewLayer' fails because 'setFullMap' hasn't finished executing. is there a solution? I'm using jquery and vanilla js so most any solution would be helpful at this point:
var jen = (function(){
function setFullMap(mapID){
jen.map = new Map(mapID);
}
function setLayer(opt){
//execute code here after jen.map is defined
}
return{
samp: function(id, opt){
setFullMap(id);
addNewLayer(opt);
}
};
})();
Thanks
solution:
var jen = (function(){
function setFullMap(mapID, callback) {
jen.map = new Map(mapID);
if(jen.map){
callback();
}
}
return {
samp: function(id, opt){
setFullMap(id, function(){
addNewLayer(opt);
}.bind(this));
}
};
})();
You will have to pass a callback function to setFullMap, and execute it once the function has completed (at the very end, before the closing }).
var jen = (function(){
function setFullMap(mapID, callback){
jen.map = new Map(mapID);
callback();
}
function setLayer(opt){
//execute code here after jen.map is defined
}
return{
samp: function(id, opt){
setFullMap(id, function() {
addNewLayer(opt);
}.bind(this));
}
};
})();
Do not forget using .bind(this) - it is very important in order to keep the original this in your callback function.
Edit:
Actually that would not work work if the Map constructor is a-synchronous. If you do not have access to the constructor and/or you cannot pass it a callback, then presumably the only (and sad) option would be to use a setTimeout or (easier) setInterval, continuously checking at defined intervals if the operation has been completed, and then fire the callback.
You could use a callback parameter:
function setFullmap(mapId,callback) {
jen.map = new Map(mapId);
callback();
}
....
samp: function(id, opt){
setFullMap(id,function() {
addNewLayer(opt);
});
}
When u dont have a way to manipulate the Map Object then u need to use a loop:
var loop=self.setInterval(function(){
if(jen.map) {
//execute code here after jen.map is defined
console.log(typeof jen.map);
window.clearInterval(loop);
}
},50);
Check jsfiddle:
http://jsfiddle.net/9yv5t/1/
I have checked the docs and it seems that there are various events you could listen to.
For example:
var m = new Map(...);
m.on('load', function () {
//execute code when the first layer is ready
});
var l = new Layer(...);
l.on('load', function () {
//execute code when the layer has been initialized
});
It's also carefully stated for the Layer.load event:
fires after layer properties for the layer are successfully populated.
This event must be successful before the layer can be added to the
map.

Set event handler on arbitrary JS function?

I'd like to write a Chrome extension that works with a particular JS-based chat application. It needs to be made aware every time the chat receives a message.
Now, I can obviously do this easily by setting up a timer and checking to see if $("chat-messages").childElements().length has increased, but I'd rather go with the more elegant method of setting up an event handler of some sort to fire every time appendChatMessage() is invoked. Is there a way to do this?
var oldfunc = appendChatMessage;
appendChatMessage = function() { eval(oldfunc); myChatMessageReceivedHandler(); }
Doesn't seem to be working.
If there is a method appendChatMessage that is called every time a new message arrives, you could do like this
var old = appendChatMessage;
appendChatMessage = function() {
// call the initial method and store the result
var result = old.apply( this, arguments );
// do your stuff here
// return the initial result
return result;
};
You have to do oldfunc(). Besides that I'd create an event to to that
var oldfunc = appendChatMessage;
appendChatMessage = function() { oldfunc(); $(document).trigger("msg_received"); }
$(document).bind("msg_received", function(params){
//do your logic when message arrives
});
You should decide which element to attach the event into and its params.
Hope this helps. Cheers
var oldfunc = appendChatMessage;
appendChatMessage = function() { eval(oldfunc(); myChatMessageReceivedHandler(); }
Should work, depending on the context.
var f = function () { console.log('foo'); }
var f2 = f;
f = function () { f2(); console.log('bar'); }
This should print:
foo
bar

Wrapping a function in Javascript / jQuery

If I have an arbitrary function myFunc, what I'm aiming to do is replace this function with a wrapped call that runs code before and after it executes, e.g.
// note: psuedo-javascript
var beforeExecute = function() { ... }
var afterExecute = function() { ... }
myFunc = wrap(myFunc, beforeExecute, afterExecute);
However, I don't have an implementation of the required wrap function. Is there anything that already exists in jQuery like this (I've had a good look through the docs but cannot see anything)? Alternatively does anybody know of a good implementation of this because I suspect that there are a bunch of edge cases that I'll miss if I try to write it myself?
(BTW - the reason for this is to do some automatic instrumentation of functions because we do a lot of work on closed devices where Javascript profilers etc. are not available. If there's a better way than this then I'd appreciate answers along those lines too.)
Here’s a wrap function which will call the before and after functions with the exact same arguments and, if supplied, the same value for this:
var wrap = function (functionToWrap, before, after, thisObject) {
return function () {
var args = Array.prototype.slice.call(arguments),
result;
if (before) before.apply(thisObject || this, args);
result = functionToWrap.apply(thisObject || this, args);
if (after) after.apply(thisObject || this, args);
return result;
};
};
myFunc = wrap(myFunc, beforeExecute, afterExecute);
The accepted implementation does not provide an option to call wrapped (original) function conditionally.
Here is a better way to wrap and unwrap a method:
/*
Replaces sMethodName method of oContext with a function which calls the wrapper
with it's list of parameters prepended by a reference to wrapped (original) function.
This provides convenience of allowing conditional calls of the
original function within the wrapper,
unlike a common implementation that supplies "before" and "after"
cross cutting concerns as two separate methods.
wrap() stores a reference to original (unwrapped) function for
subsequent unwrap() calls.
Example:
=========================================
var o = {
test: function(sText) { return sText; }
}
wrap('test', o, function(fOriginal, sText) {
return 'before ' + fOriginal(sText) + ' after';
});
o.test('mytext') // returns: "before mytext after"
unwrap('test', o);
o.test('mytext') // returns: "mytext"
=========================================
*/
function wrap(sMethodName, oContext, fWrapper, oWrapperContext) {
var fOriginal = oContext[sMethodName];
oContext[sMethodName] = function () {
var a = Array.prototype.slice.call(arguments);
a.unshift(fOriginal.bind(oContext));
return fWrapper.apply(oWrapperContext || oContext, a);
};
oContext[sMethodName].unwrapped = fOriginal;
};
/*
Reverts method sMethodName of oContext to reference original function,
the way it was before wrap() call
*/
function unwrap(sMethodName, oContext) {
if (typeof oContext[sMethodName] == 'function') {
oContext[sMethodName] = oContext[sMethodName].unwrapped;
}
};
This is the example I would use
<script type="text/javascript">
var before = function(){alert("before")};
var after = function(param){alert(param)};
var wrap = function(func, wrap_before, wrap_after){
wrap_before.call();
func.call();
wrap_after.call();
};
wrap(function(){alert("in the middle");},before,function(){after("after")});
</script>
You could do something like:
var wrap = function(func, pre, post)
{
return function()
{
var callee = arguments.callee;
var args = arguments;
pre();
func.apply(callee, args);
post();
};
};
This would allow you to do:
var someFunc = function(arg1, arg2)
{
console.log(arg1);
console.log(arg2);
};
someFunc = wrap(
someFunc,
function() { console.log("pre"); },
function() { console.log("post"); });
someFunc("Hello", 27);
Which gives me an output in Firebug of:
pre
Hello
27
post
The important part when wrapping this way, is passing your arguments from the new function back to the original function.
Maybe I'm wrong, but I think you can directly create an anonym function and assign it to myFunc:
myFunc = function(){
BeforeFunction();
myFunc();
AfterFunction();
}
In this way you can control the arguments of every function.

Categories