165

I understand passing in a function to another function as a callback and having it execute, but I'm not understanding the best implementation to do that. I'm looking for a very basic example, like this:

var myCallBackExample = {
    myFirstFunction : function( param1, param2, callback ) {
        // Do something with param1 and param2.
        if ( arguments.length == 3 ) {
            // Execute callback function.
            // What is the "best" way to do this?
        }
    },
    mySecondFunction : function() {
        myFirstFunction( false, true, function() {
            // When this anonymous function is called, execute it.
        });
    }
};

In myFirstFunction, if I do return new callback(), then it works and executes the anonymous function, but that doesn't seem like the correct approach to me.

3
  • Correct in what sense? Typically callbacks are used for event handlers--most notably Ajax calls, which are asynchronous--basically things where you don't know when (or if) a resposne will come. Commented Jan 27, 2009 at 11:41
  • 2
    by the way arguments are array like but not array , so you can't do argument.length but you can convert it into an array using slice method... Commented Mar 26, 2011 at 0:52
  • 1
    @paul, although you are right that arguments is not an array, you can still reference its length as arguments.length -- give it a try. This property refers to the number of arguments actually passed in, and not necessarily the number of parameters in the function signature. Commented Jun 14, 2011 at 21:32

8 Answers 8

133

You can just say

callback();

Alternately you can use the call method if you want to adjust the value of this within the callback.

callback.call( newValueForThis);

Inside the function this would be whatever newValueForThis is.

Sign up to request clarification or add additional context in comments.

Comments

91

You should check if the callback exists, and is an executable function:

if (callback && typeof(callback) === "function") {
    // execute the callback, passing parameters as necessary
    callback();
}

A lot of libraries (jQuery, dojo, etc.) use a similar pattern for their asynchronous functions, as well as node.js for all async functions (nodejs usually passes error and data to the callback). Looking into their source code would help!

4 Comments

Why do you cast callback to string and then check its type? Will this enhance performance? This is like checking the type, checking if the converted boolean returns true and then checking its type again and testing it against the string... Could you explain why?
I am curious why you need the first assertion for callback... is it to check null or undefined? Wouldn't typeof(callback) achieve that for you? typeof(null) === "Object", typeof("undefined") === "undefined"
Short-circuit AND. If the callback doesn't exist, don't bother computing its type. Though, you're right. It isn't needed with the typeof(), but I'll do a jsperf and see if the short-circuit is worth it.
@headacheCoder - callback is not being cast to a string, its type is being checked to see if it is a function, before it is called. The code presumably accepts callback as an argument, and is uncertain that the argument is of a callable type — or perhaps the arguments are of various types in an attempt to provide a form of polymorphism where code might react differently to different typeof arguments.
34

There are 3 main possibilities to execute a function:

var callback = function(x, y) {
    // "this" may be different depending how you call the function
    alert(this);
};
  1. callback(argument_1, argument_2);
  2. callback.call(some_object, argument_1, argument_2);
  3. callback.apply(some_object, [argument_1, argument_2]);

The method you choose depends whether:

  1. You have the arguments stored in an Array or as distinct variables.
  2. You want to call that function in the context of some object. In this case, using the "this" keyword in that callback would reference the object passed as argument in call() or apply(). If you don't want to pass the object context, use null or undefined. In the latter case the global object would be used for "this".

Docs for Function.call, Function.apply

Comments

6

Callbacks are about signals and "new" is about creating object instances.

In this case it would be even more appropriate to execute just "callback();" than "return new callback()" because you aren't doing anything with a return value anyway.

(And the arguments.length==3 test is really clunky, fwiw, better to check that callback param exists and is a function.)

Comments

6

the proper implementation would be:

if( callback ) callback();

this makes the callback parameter optional..

1 Comment

What if the callback argument is not a function?
2

You can use:

if (callback && typeof(callback) === "function") {
    callback();
}

The below example is little more comprehensive:

function mySandwich(param1, param2, callback) {
  alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
  var sandwich = {
      toppings: [param1, param2]
    },
    madeCorrectly = (typeof(param1) === "string" && typeof(param2) === "string") ? true : false;
  if (callback && typeof(callback) === "function") {
    callback.apply(sandwich, [madeCorrectly]);
  }
}

mySandwich('ham', 'cheese', function(correct) {
  if (correct) {
    alert("Finished eating my " + this.toppings[0] + " and " + this.toppings[1] + " sandwich.");
  } else {
    alert("Gross!  Why would I eat a " + this.toppings[0] + " and " + this.toppings[1] + " sandwich?");
  }
});

Comments

1

Here is a basic example that explains the callback() function in JavaScript:

var x = 0;

function testCallBack(param1, param2, callback) {
  alert('param1= ' + param1 + ', param2= ' + param2 + ' X=' + x);
  if (callback && typeof(callback) === "function") {
    x += 1;
    alert("Calla Back x= " + x);
    x += 1;
    callback();
  }
}

testCallBack('ham', 'cheese', function() {
  alert("Function X= " + x);
});

JSFiddle

Comments

1

function checkCallback(cb) {
  if (cb || cb != '') {
    if (typeof window[cb] === 'undefined') alert('Callback function not found.');
    else window[cb].call(this, Arg1, Arg2);
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.