5

I'm trying to return a value after a function has been invoked n number of times. Here's what I have so far:

function spyOn(fn) { //takes in function as argument
//returns function that can be called and behaves like argument
var count = 0;

var inner = function(){
  count++;
}

inner.callCount = function(){return count};

}

And this is how I'm testing it:

for (var i = 0; i < 99; i++) {
  spyOn();
}

I feel like this is a simple problem that I should be able to simply google, but I haven't been able to find a solution. Thanks!

Brayheart
  • 167
  • 2
  • 16
  • 2
    Well the first problem I see is that you never call the original function. – gforce301 Jan 26 '18 at 18:34
  • 2
    Possible duplicate of [How do I find out how many times a function is called with javascript/jquery?](https://stackoverflow.com/questions/8517562/how-do-i-find-out-how-many-times-a-function-is-called-with-javascript-jquery) – Herohtar Jan 26 '18 at 18:35
  • You want to `return inner` from `spyOn`, and then use *that* in the loop – Bergi Jan 26 '18 at 18:36
  • @Bergi still going to need more than that to work unless you are assuming OP knows to store that is returned into variable and use that instead of calling spyOn multiple times... – epascarello Jan 26 '18 at 18:37
  • @epascarello Yeah, that's what I meant by "use that [returned function] in the loop". And then there's "*behaves like argument* `fn`"… – Bergi Jan 26 '18 at 18:41
  • @Herohtar I did find that solution and did my best to implement it, however I was unable to do so. If you feel its a duplicate I'll take it down after I figure out how to fix my issue. – Brayheart Jan 26 '18 at 18:47

2 Answers2

2

It looks like your spyOn function should accept a function fn as an argument and return a function (lets call it inner) that calls fn with the arguments inner is called with and returns the value the fn returns:

const spiedCube = spyOn( cube, function ( count, result ) {
  if ( count % 3 === 0 )
    console.log( `Called ${count} times. Result: ${result}` );
} );

for ( let i = 0; i < 12; i++ )
  console.log( spiedCube( i ) );

//

function spyOn( fn, handler ) {
    
    let count = 0;
  
    return function inner ( ) {
        count++;
        const result = fn( ...arguments );
        handler( count, result );
        return result;
    };
    
}

function cube ( x ) {
    return x**3;
}
Paul
  • 139,544
  • 27
  • 275
  • 264
  • This is the answer I was preparing too, but yours is better as you thought of a handler. Not sure why you put `if (count % 3 === 0)` in your example though, could be simpler. – RaphaMex Jan 26 '18 at 19:17
  • @RaphaMex I just wanted some regular output to demonstrate the handler working in the "Run code snippet" demo. It's not intended to be used verbatim by the OP. – Paul Jan 26 '18 at 19:29
1

You can do something like an interceptor of your function:

This is a tiny version, from now you can add the arguments and necessary behavior, the most important here it's how your function was wrapped by an interceptor and every call will increment a count of invocations.

function spyOn(fn) {
  var count = 0;
  
  return function() {
    fn();
    count++;

    console.log(count);
  }
}

var myFunction = function() {
  console.log("called!");
};

var spy = spyOn(myFunction);

for (var i = 0; i < 99; i++) {
  spy();
}
halfer
  • 19,824
  • 17
  • 99
  • 186
Ele
  • 33,468
  • 7
  • 37
  • 75