343

All I need to do is to execute a callback function when my current function execution ends.

function LoadData() 
{
    alert('The data has been loaded');
    //Call my callback with parameters. For example,
    //callback(loadedData , currentObject);
}

A consumer for this function should be like this:

object.LoadData(success);

function success(loadedData , currentObject) 
{
  //Todo: some action here 
}

How do I implement this?

Rubén
  • 34,714
  • 9
  • 70
  • 166
Amgad Fahmi
  • 4,349
  • 3
  • 19
  • 18
  • 3
    `object.LoadData(success)` call must be **after** `function success` is defined. Otherwise, you will get an error telling you the function is not defined. – J. Bruni Dec 29 '11 at 13:41

11 Answers11

595

Actually, your code will pretty much work as is, just declare your callback as an argument and you can call it directly using the argument name.

The basics

function doSomething(callback) {
    // ...

    // Call the callback
    callback('stuff', 'goes', 'here');
}

function foo(a, b, c) {
    // I'm the callback
    alert(a + " " + b + " " + c);
}

doSomething(foo);

That will call doSomething, which will call foo, which will alert "stuff goes here".

Note that it's very important to pass the function reference (foo), rather than calling the function and passing its result (foo()). In your question, you do it properly, but it's just worth pointing out because it's a common error.

More advanced stuff

Sometimes you want to call the callback so it sees a specific value for this. You can easily do that with the JavaScript call function:

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback) {
    // Call our callback, but using our own instance as the context
    callback.call(this);
}

function foo() {
    alert(this.name);
}

var t = new Thing('Joe');
t.doSomething(foo);  // Alerts "Joe" via `foo`

You can also pass arguments:

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback, salutation) {
    // Call our callback, but using our own instance as the context
    callback.call(this, salutation);
}

function foo(salutation) {
    alert(salutation + " " + this.name);
}

var t = new Thing('Joe');
t.doSomething(foo, 'Hi');  // Alerts "Hi Joe" via `foo`

Sometimes it's useful to pass the arguments you want to give the callback as an array, rather than individually. You can use apply to do that:

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback) {
    // Call our callback, but using our own instance as the context
    callback.apply(this, ['Hi', 3, 2, 1]);
}

function foo(salutation, three, two, one) {
    alert(salutation + " " + this.name + " - " + three + " " + two + " " + one);
}

var t = new Thing('Joe');
t.doSomething(foo);  // Alerts "Hi Joe - 3 2 1" via `foo`
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I know it will work if i don't have any parameters like the example you wrote but when i try to pass a function with parameters it's throwing an exception and telling me the function is not defined – Amgad Fahmi Feb 03 '10 at 09:29
  • @TiTaN: That's strange, there's nothing special about passing parameters into the callback. The callback reference you pass into your function is a function reference like any other, you can do all the normal things with it. – T.J. Crowder Feb 03 '10 at 09:32
  • 4
    @everyone who answered: I think TiTaN's problem is that he doesn't know how to pass a function that requires arguments into a callback that doesn't pass any arguments. Think `setTimeout()`. The answer is to wrap the callback in a closure: `doSomething(function(){foo('this','should','work')})` – slebetman Feb 03 '10 at 10:12
  • Someone point TiTaN to a thread (preferably on SO) discussing the issue above, my search-fu is weak today. – slebetman Feb 03 '10 at 10:13
  • cool hints, it is mandatory to pass callback as argument or just kind of good practice, in which case why please? thanks – Webwoman Feb 05 '19 at 21:32
  • 1
    @Webwoman - It depends on your use case. You could pass it as an argument, or include it in some kind of settings/options object, or any of several other options. – T.J. Crowder Feb 06 '19 at 07:50
83

It is good practice to make sure the callback is an actual function before attempting to execute it:

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

  callback();
}
Donald A Nummer Jr
  • 1,137
  • 9
  • 11
67

My 2 cent. Same but different...

<script>
    dosomething("blaha", function(){
        alert("Yay just like jQuery callbacks!");
    });


    function dosomething(damsg, callback){
        alert(damsg);
        if(typeof callback == "function") 
        callback();
    }
</script>
K. Kilian Lindberg
  • 2,918
  • 23
  • 30
13
function loadData(callback) {

    //execute other requirement

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

loadData(function(){

   //execute callback

});
AlexB
  • 7,302
  • 12
  • 56
  • 74
arun bahal
  • 328
  • 3
  • 13
  • 6
    Please consider editing your post to add more explanation about what your code does and why it will solve the problem. An answer that mostly just contains code (even if it's working) usually wont help the OP to understand their problem. However in this case, this is a very old question with highly regarded answers already posted, it might not be worth your while answering this when there are newer questions that could do with more attention. – SuperBiasedMan Sep 07 '15 at 10:29
  • 1
    I like this answer its str8 forward demonstration of what people want to see. – JΛYDΞV Mar 23 '20 at 19:32
5
   function callback(e){
      return e;
   }
    var MyClass = {
       method: function(args, callback){
          console.log(args);
          if(typeof callback == "function")
          callback();
       }    
    }

==============================================

MyClass.method("hello",function(){
    console.log("world !");
});

==============================================

Result is:

hello world !
Ahmet Can Güven
  • 5,392
  • 4
  • 38
  • 59
Eyad Farra
  • 4,403
  • 1
  • 24
  • 26
4

Some of the answers, while correct may be a little tricky to understand. Here is an example in layman's terms:

var users = ["Sam", "Ellie", "Bernie"];

function addUser(username, callback)
{
    setTimeout(function()
    {
        users.push(username);
        callback();
    }, 200);
}

function getUsers()
{
    setTimeout(function()
    {
        console.log(users);
    }, 100);
}

addUser("Jake", getUsers);

The callback means, "Jake" is always added to the users before displaying the list of users with console.log.

Source (YouTube)

Dan Bray
  • 7,242
  • 3
  • 52
  • 70
4

If you want to execute a function when something is done. One of a good solution is to listen to events. For example, I'll implement a Dispatcher, a DispatcherEvent class with ES6,then:

let Notification = new Dispatcher()
Notification.on('Load data success', loadSuccessCallback)

const loadSuccessCallback = (data) =>{
   ...
}
//trigger a event whenever you got data by
Notification.dispatch('Load data success')

Dispatcher:

class Dispatcher{
  constructor(){
    this.events = {}
  }

  dispatch(eventName, data){
    const event = this.events[eventName]
    if(event){
      event.fire(data)
    }
  }

  //start listen event
  on(eventName, callback){
    let event = this.events[eventName]
    if(!event){
      event = new DispatcherEvent(eventName)
      this.events[eventName] = event
    }
    event.registerCallback(callback)
  }

  //stop listen event
  off(eventName, callback){
    const event = this.events[eventName]
    if(event){
      delete this.events[eventName]
    }
  }
}

DispatcherEvent:

class DispatcherEvent{
  constructor(eventName){
    this.eventName = eventName
    this.callbacks = []
  }

  registerCallback(callback){
    this.callbacks.push(callback)
  }

  fire(data){
    this.callbacks.forEach((callback=>{
      callback(data)
    }))
  }
}

Happy coding!

p/s: My code is missing handle some error exceptions

hien
  • 1,988
  • 2
  • 17
  • 13
2

When calling the callback function, we could use it like below:

consumingFunction(callbackFunctionName)

Example:

// Callback function only know the action,
// but don't know what's the data.
function callbackFunction(unknown) {
  console.log(unknown);
}

// This is a consuming function.
function getInfo(thenCallback) {
  // When we define the function we only know the data but not
  // the action. The action will be deferred until excecuting.
  var info = 'I know now';
  if (typeof thenCallback === 'function') {
    thenCallback(info);    
  }
}

// Start.
getInfo(callbackFunction); // I know now

This is the Codepend with full example.

Eric Tan
  • 1,377
  • 15
  • 14
1
function LoadData(callback) 
{
    alert('the data have been loaded');
    callback(loadedData, currentObject);
}
thor
  • 21,418
  • 31
  • 87
  • 173
Andreas Bonini
  • 44,018
  • 30
  • 122
  • 156
1
     function login(email, password, callback) {
         //verify the user
         const users = [
          { email: "abc@gmail.com", password: "123" },
          { email: "xyz@gmail.com", password: "xyz" }
         ];

         const user = users.find(
           (user) => user.email === email && user.password === password
         );
         callback(user);
       `enter code here`}

    function redirect(user) {
       if (user) {
          //user is successfully logged in
          console.log("user is successfully logged in ");
       } else {
         console.log("Incorrect credentials ");
       } 
    }

    
    login("abc@gmail.com", "123", redirect);

I hope this example will help everyone who wants to know about the callback in JS

Muhammad Atif Akram
  • 1,204
  • 1
  • 4
  • 12
0

Try:

function LoadData (callback)
{
    // ... Process whatever data
    callback (loadedData, currentObject);
}

Functions are first class in JavaScript; you can just pass them around.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
K Prime
  • 5,809
  • 1
  • 25
  • 19