Defining Callbacks for custom Javascript Functions

103 views Asked by At

The scenario is i am writing some custom javascript method lets say suppose.

function callMe(){
  //Do some stuff and return.
}

Now i want to add some functions, i am not sure if they will be treated as callback but which will be triggered at some point as the callMe() is being executed. Lets say i want the beforecallMe() needs to be executed as soon as somebody calls callMe() methof

function beforecallMe(){
// Do something and continue with callMe method

}

Again i want to call a method as soon as the callMe has executed its part of code, lets say method afterCallMe() .

function afterCallMe(){
 //Triggered after callMe has executed
}

So is there any possible way i can do this in Callbacks or any other way.

Also i want to know if its possible call other custom functions as callbacks when a particular function is going to execute or has executed, somewhat a trigger.

For e.g : There is a method sendmail() after which i wish to call sometimes sendReport() or startaProgram() or doSomething() and so on. Is there any way to do achieve this ?

6

There are 6 answers

0
Prabodh M On BEST ANSWER

I have found answer in the comments as mentioned by Dan Davis in comments.

And the fiddle for the same is

http://jsfiddle.net/3h3f2y93/1/

and Code is :

Function.prototype.after=function(fn){
    var f=this;
    return function(){
        return fn.apply(this, arguments), f.apply(this, arguments);
    }
};

Function.prototype.before=function(fn){
    var f=this;
    return function(){
        return f.apply(this, arguments), fn.apply(this, arguments);
    }
};


function say1(){ alert(1); }
function say2(){ alert(2); }
function say3(){ alert(3); }

//say 2 before you say 1 and after you say 3:
 say2.before(say1).after(say3)();
0
Scheda On

There's plenty of ways to handle this.

Here's two.

One using a function parameter and an object with functions inside it then using callbacks. They're both valid, but callbacks are a bit simpler, if you ask me.

//you can pass a parameter and
//use that in a switch statement
//to decide what to do
var funcs = {
    start: function(next) {

        switch (next) {
            case 1:
                this.startProgram();
                break;

            case 2:
                this.sendReport();
                break;

            case 3:
                this.doOtherThing();
                break;

            default:
                console.log('do nada');
                break;
        }
    },

    startProgram: function() {
        console.log("starting a program");
    },

    sendReport: function() {
        console.log("sending report");
    },

    doOtherThing: function() {
        console.log("Doing something else");
    }
};

funcs.start(1)
funcs.start()

//Or you can do it with callbacks
function doSomethingElse(callback) {
    console.log("doing something");
    callback();
}

doSomethingElse(function() {
    console.log("I'm a callback!");
});
0
harveytoro On

You could just do this

function callMe()
{
    beforeCallMe();
    // CallMe code here
    afterCallMe();
}

beforeCallMe() will a execute before the rest of the callMe() method and then afterCallMe() will be executed;

0
Safeer Hussain On

You can define the function as follows:

function callMe(beforeCall, afterCall){
  if(typeof(beforeCall) === "function") beforeCall();

  // Your call me code goes here...

  if(typeof(afterCall) === "function") afterCall();
}

Usage:

callMe(); // No callbacks
callMe(null, afterCall); // Will only call the afterCall
callMe(beforeCall, afterCall); // Will call both the beforeCall and afterCall

function beforeCall() {
  // before call function
}
function afterCall() {
  // after call function
}

or you can define as anonymous functions:

callMe(function () {
  // before call function
}, function () {
  // after call function
}); 
0
jwatts1980 On

There are a hundred ways to do something like this. Here is a function that will accept either 3 functions, or an object with the functions defined as parameters.

<script>
    function write(txt) {
        document.getElementById("test").innerHTML = txt;
    }

    function append(txt) {
        var inner = document.getElementById("test").innerHTML;
        document.getElementById("test").innerHTML = inner + "<br>" + txt;
    }

    function callMe(callFunctionOrObject, callBefore, callAfter) {
        if (!callFunctionOrObject) return;

        if (typeof callFunctionOrObject === "object") {
            if (typeof callFunctionOrObject.callBefore === "function") {
                callFunctionOrObject.callBefore();
            }
            if (typeof callFunctionOrObject.call === "function") {
                callFunctionOrObject.call();
            }
            if (typeof callFunctionOrObject.callAfter === "function") {
                callFunctionOrObject.callAfter();
            }
        }
        else if (typeof callFunctionOrObject === "function") {
            if (typeof callBefore === "function") {
                callBefore();
            }
            callFunctionOrObject();
            if (typeof callAfter === "function") {
                callAfter();
            }
        }
    }

    //EXAMPLE USAGE
    append("First Test");
    callMe({
        "callBefore": function() { append("Before call 1"); },
        "call": function() { append("call 1"); },
        "callAfter": function() { append("After call 1"); }
    });

    append("Second Test");
    callMe(
        function() { append("call 2"); },
        function() { append("Before call 2"); },
        function() { append("After call 2"); }
    );
</script>

<div id="test"></div>

The Fiddle

0
Amit On

You can do this dynamically, setup a before and/or after handler, as well as setup context arguments for each function.

The code below has 2 important functions setupFunctionTriggers & removeFunctionTriggers. The rest of the code and html are just there to show how to use these functions.

A few key techniques used:

  1. A Named function can be treated like a variable. It's "value" can be copied read and assigned to (copied and replaced).
  2. Use new Function() to execute dynamic code.
  3. new Function('return '+funcName+';')(); Will return the named function itself.
  4. new Function('func', funcName+'=func;')(wrapperFunc); Will replace the function with a new function.

function setupFunctionTriggers(funcName, before, after, beforeArgs, afterArgs) {
  var func = new Function('return '+funcName+';')();
  var wrapperFunc = function() {
    if(before instanceof Function)
      before.apply(this, beforeArgs);
    
    var ret = func.apply(this, arguments);

    if(after instanceof Function)
      after.apply(this, afterArgs);

    return ret;
  };

  new Function('func', funcName+'=func;')(wrapperFunc);
  return func;
}

function removeFunctionTriggers(funcName, original) {
  new Function('func', funcName+'=func;')(original);
}



var log = '';

function callMe(val) {
  log += 'Inside callMe(' + val + ')\n';
  return 'Called me!';
}

function before(val) {
  log += 'Before callMe, with val=' + val + '\n';
}

function after() {
  log += 'After callMe\n';
}


log += 'Call normal function\n';
callMe(12);

log += '\nSetup triggers...\n';
var originalCallMe = setupFunctionTriggers('callMe', before , after, ['B4!']);

var ret = callMe(34);
log += 'callMe returned: ' + ret;

log += '\n\nCall original function (triggers still attached)\n';
originalCallMe(56);

log += '\nReverting...\n';
removeFunctionTriggers('callMe', originalCallMe);

callMe(78);

document.getElementById('log').innerHTML = '<pre>'+log+'</pre>';
<span id="log"></span>