How to explain callbacks in plain english? How are they different from calling one function from another function?

后端 未结 30 1519
时光说笑
时光说笑 2020-11-22 11:13

How to explain callbacks in plain English? How are they different from calling one function from another function taking some context from the calling function? How can thei

相关标签:
30条回答
  • 2020-11-22 11:35

    Plain and simple: A callback is a function that you give to another function, so that it can call it.

    Usually it is called when some operation is completed. Since you create the callback before giving it to the other function, you can initialize it with context information from the call site. That is why it is named a call*back* - the first function calls back into the context from where it was called.

    0 讨论(0)
  • 2020-11-22 11:37

    For teaching callbacks, you have to teach the pointer first. Once the students understand the idea of pointer to a variable, idea of callbacks will get easier. Assuming you are using C/C++, these steps can be followed.

    • First show your students how to use and manipulate variables using pointers alongside using the normal variable identifiers.
    • Then teach them there are things that can be done only with pointers(like passing a variable by reference).
    • Then tell them how executable code or functions are just like some other data(or variables) in the memory. So, functions also have addresses or pointers.
    • Then show them how functions can be called with function pointers and tell these are called callbacks.
    • Now, the question is, why all these hassle for calling some functions? What is the benefit? Like data pointers, function pointer aka callbacks has some advantages over using normal identifiers.
    • The first one is, function identifiers or function names cannot be used as normal data. I mean, you cannot make a data structure with functions(like an array or a linked list of functions). But with callbacks, you can make an array, a linked list or use them with other data like in dictionary of key-value pairs or trees, or any other things. This is a powerful benefit. And other benefits are actually child of this one.
    • The most common use of callbacks is seen in event driver programming. Where one or more functions are executed based on some incoming signal. With callbacks, a dictionary can be maintained to map signals with callbacks. Then the input signal resolution and execution of corresponding code become much easier.
    • The second use of callbacks coming in my mind is higher order functions. The functions which takes other functions as input arguments. And to send functions as arguments, we need callbacks. An example can be a function which take an array and a callback. Then it performs the callback on each of the item of the array and return the results in another array. If we pass the function a doubling callback, we get a doubled valued array. If we pass a squaring callback, we get squares. For square roots, just send appropriate callback. This cannot be done with normal functions.

    There might many more things. Involve the students and they will discover. Hope this helps.

    0 讨论(0)
  • 2020-11-22 11:37

    In plain english a callback is a promise. Joe, Jane, David and Samantha share a carpool to work. Joe is driving today. Jane, David and Samantha have a couple of options:

    1. Check the window every 5 minutes to see if Joe is out
    2. Keep doing their thing until Joe rings the door bell.

    Option 1: This is more like a polling example where Jane would be stuck in a "loop" checking if Joe is outside. Jane can't do anything else in the mean time.

    Option 2: This is the callback example. Jane tells Joe to ring her doorbell when he's outside. She gives him a "function" to ring the door bell. Joe does not need to know how the door bell works or where it is, he just needs to call that function i.e. ring the door bell when he's there.

    Callbacks are driven by "events". In this example the "event" is Joe's arrival. In Ajax for example events can be "success" or "failure" of the asynchronous request and each can have the same or different callbacks.

    In terms of JavaScript applications and callbacks. We also need to understand "closures" and application context. What "this" refers to can easily confuse JavaScript developers. In this example within each person's "ring_the_door_bell()" method/callback there might be some other methods that each person need to do based on their morning routine ex. "turn_off_the_tv()". We would want "this" to refer to the "Jane" object or the "David" object so that each can setup whatever else they need done before Joe picks them up. This is where setting up the callback with Joe requires parodying the method so that "this" refers to the right object.

    Hope that helps!

    0 讨论(0)
  • 2020-11-22 11:38

    How to explain callbacks in plain English?

    In plain English, a callback function is like a Worker who "calls back" to his Manager when he has completed a Task.

    How are they different from calling one function from another function taking some context from the calling function?

    It is true that you are calling a function from another function, but the key is that the callback is treated like an Object, so you can change which Function to call based on the state of the system (like the Strategy Design Pattern).

    How can their power be explained to a novice programmer?

    The power of callbacks can easily be seen in AJAX-style websites which need to pull data from a server. Downloading the new data may take some time. Without callbacks, your entire User Interface would "freeze up" while downloading the new data, or you would need to refresh the entire page rather than just part of it. With a callback, you can insert a "now loading" image and replace it with the new data once it is loaded.

    Some code without a callback:

    function grabAndFreeze() {
        showNowLoading(true);
        var jsondata = getData('http://yourserver.com/data/messages.json');
        /* User Interface 'freezes' while getting data */
        processData(jsondata);
        showNowLoading(false);
        do_other_stuff(); // not called until data fully downloaded
    }
    
    function processData(jsondata) { // do something with the data
       var count = jsondata.results ? jsondata.results.length : 0;
       $('#counter_messages').text(['Fetched', count, 'new items'].join(' '));
       $('#results_messages').html(jsondata.results || '(no new messages)');
    }
    

    With Callback:

    Here is an example with a callback, using jQuery's getJSON:

    function processDataCB(jsondata) { // callback: update UI with results
       showNowLoading(false);
       var count = jsondata.results ? jsondata.results.length : 0;
       $('#counter_messages').text(['Fetched', count, 'new items'].join(' '));
       $('#results_messages').html(jsondata.results || '(no new messages)');
    }
    
    function grabAndGo() { // and don't freeze
        showNowLoading(true);
        $('#results_messages').html(now_loading_image);
        $.getJSON("http://yourserver.com/data/messages.json", processDataCB);
        /* Call processDataCB when data is downloaded, no frozen User Interface! */
        do_other_stuff(); // called immediately
    }
    

    With Closure:

    Often the callback needs to access state from the calling function using a closure, which is like the Worker needing to get information from the Manager before he can complete his Task. To create the closure, you can inline the function so it sees the data in the calling context:

    /* Grab messages, chat users, etc by changing dtable. Run callback cb when done.*/
    function grab(dtable, cb) { 
        if (null == dtable) { dtable = "messages"; }
        var uiElem = "_" + dtable;
        showNowLoading(true, dtable);
        $('#results' + uiElem).html(now_loading_image);
        $.getJSON("http://yourserver.com/user/"+dtable+".json", cb || function (jsondata) {
           // Using a closure: can "see" dtable argument and uiElem variables above.
           var count = jsondata.results ? jsondata.results.length : 0, 
               counterMsg = ['Fetched', count, 'new', dtable].join(' '),
               // no new chatters/messages/etc
               defaultResultsMsg = ['(no new ', dtable, ')'].join(''); 
           showNowLoading(false, dtable);
           $('#counter' + uiElem).text(counterMsg);
           $('#results'+ uiElem).html(jsondata.results || defaultResultsMsg);
        });
        /* User Interface calls cb when data is downloaded */
    
        do_other_stuff(); // called immediately
    }
    

    Usage:

    // update results_chatters when chatters.json data is downloaded:
    grab("chatters"); 
    // update results_messages when messages.json data is downloaded
    grab("messages"); 
    // call myCallback(jsondata) when "history.json" data is loaded:
    grab("history", myCallback); 
    

    Closure

    Finally, here is a definition of closure from Douglas Crockford:

    Functions can be defined inside of other functions. The inner function has access to the vars and parameters of the outer function. If a reference to an inner function survives (for example, as a callback function), the outer function's vars also survive.

    See also:

    • http://javascript.crockford.com/survey.html
    • http://api.jquery.com/jQuery.when/
    • http://api.jquery.com/jQuery.getJSON/
    • http://github.com/josher19/jQuery-Parse
    0 讨论(0)
  • 2020-11-22 11:38

    “In computer programming, a callback is a reference to executable code, or a piece of executable code, that is passed as an argument to other code. This allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer.” - Wikipedia

    Callback in C using Function Pointer

    In C, callback is implemented using Function Pointer. Function Pointer - as the name suggests, is a pointer to a function.

    For example, int (*ptrFunc) ();

    Here, ptrFunc is a pointer to a function that takes no arguments and returns an integer. DO NOT forget to put in the parenthesis, otherwise the compiler will assume that ptrFunc is a normal function name, which takes nothing and returns a pointer to an integer.

    Here is some code to demonstrate the function pointer.

    #include<stdio.h>
    int func(int, int);
    int main(void)
    {
        int result1,result2;
        /* declaring a pointer to a function which takes
           two int arguments and returns an integer as result */
        int (*ptrFunc)(int,int);
    
        /* assigning ptrFunc to func's address */                    
        ptrFunc=func;
    
        /* calling func() through explicit dereference */
        result1 = (*ptrFunc)(10,20);
    
        /* calling func() through implicit dereference */        
        result2 = ptrFunc(10,20);            
        printf("result1 = %d result2 = %d\n",result1,result2);
        return 0;
    }
    
    int func(int x, int y)
    {
        return x+y;
    }
    

    Now let us try to understand the concept of Callback in C using function pointer.

    The complete program has three files: callback.c, reg_callback.h and reg_callback.c.

    /* callback.c */
    #include<stdio.h>
    #include"reg_callback.h"
    
    /* callback function definition goes here */
    void my_callback(void)
    {
        printf("inside my_callback\n");
    }
    
    int main(void)
    {
        /* initialize function pointer to
        my_callback */
        callback ptr_my_callback=my_callback;                        
        printf("This is a program demonstrating function callback\n");
        /* register our callback function */
        register_callback(ptr_my_callback);                          
        printf("back inside main program\n");
        return 0;
    }
    
    /* reg_callback.h */
    typedef void (*callback)(void);
    void register_callback(callback ptr_reg_callback);
    
    
    /* reg_callback.c */
    #include<stdio.h>
    #include"reg_callback.h"
    
    /* registration goes here */
    void register_callback(callback ptr_reg_callback)
    {
        printf("inside register_callback\n");
        /* calling our callback function my_callback */
        (*ptr_reg_callback)();                               
    }
    

    If we run this program, the output will be

    This is a program demonstrating function callback inside register_callback inside my_callback back inside main program

    The higher layer function calls a lower layer function as a normal call and the callback mechanism allows the lower layer function to call the higher layer function through a pointer to a callback function.

    Callback in Java Using Interface

    Java does not have the concept of function pointer It implements Callback mechanism through its Interface mechanism Here instead of a function pointer, we declare an Interface having a method which will be called when the callee finishes its task

    Let me demonstrate it through an example:

    The Callback Interface

    public interface Callback
    {
        public void notify(Result result);
    }
    

    The Caller or the Higher Level Class

    public Class Caller implements Callback
    {
    Callee ce = new Callee(this); //pass self to the callee
    
    //Other functionality
    //Call the Asynctask
    ce.doAsynctask();
    
    public void notify(Result result){
    //Got the result after the callee has finished the task
    //Can do whatever i want with the result
    }
    }
    

    The Callee or the lower layer function

    public Class Callee {
    Callback cb;
    Callee(Callback cb){
    this.cb = cb;
    }
    
    doAsynctask(){
    //do the long running task
    //get the result
    cb.notify(result);//after the task is completed, notify the caller
    }
    }
    

    Callback Using EventListener pattern

    • List item

    This pattern is used to notify 0 to n numbers of Observers/Listeners that a particular task has finished

    • List item

    The difference between Callback mechanism and EventListener/Observer mechanism is that in callback, the callee notifies the single caller, whereas in Eventlisener/Observer, the callee can notify anyone who is interested in that event (the notification may go to some other parts of the application which has not triggered the task)

    Let me explain it through an example.

    The Event Interface

    public interface Events {
    
    public void clickEvent();
    public void longClickEvent();
    }
    

    Class Widget

    package com.som_itsolutions.training.java.exampleeventlistener;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class Widget implements Events{
    
        ArrayList<OnClickEventListener> mClickEventListener = new ArrayList<OnClickEventListener>(); 
        ArrayList<OnLongClickEventListener> mLongClickEventListener = new ArrayList<OnLongClickEventListener>();
    
        @Override
        public void clickEvent() {
            // TODO Auto-generated method stub
            Iterator<OnClickEventListener> it = mClickEventListener.iterator();
                    while(it.hasNext()){
                        OnClickEventListener li = it.next();
                        li.onClick(this);
                    }   
        }
        @Override
        public void longClickEvent() {
            // TODO Auto-generated method stub
            Iterator<OnLongClickEventListener> it = mLongClickEventListener.iterator();
            while(it.hasNext()){
                OnLongClickEventListener li = it.next();
                li.onLongClick(this);
            }
    
        }
    
        public interface OnClickEventListener
        {
            public void onClick (Widget source);
        }
    
        public interface OnLongClickEventListener
        {
            public void onLongClick (Widget source);
        }
    
        public void setOnClickEventListner(OnClickEventListener li){
            mClickEventListener.add(li);
        }
        public void setOnLongClickEventListner(OnLongClickEventListener li){
            mLongClickEventListener.add(li);
        }
    }
    

    Class Button

    public class Button extends Widget{
    private String mButtonText;
    public Button (){
    } 
    public String getButtonText() {
    return mButtonText;
    }
    public void setButtonText(String buttonText) {
    this.mButtonText = buttonText;
    }
    }
    

    Class Checkbox

    public class CheckBox extends Widget{
    private boolean checked;
    public CheckBox() {
    checked = false;
    }
    public boolean isChecked(){
    return (checked == true);
    }
    public void setCheck(boolean checked){
    this.checked = checked;
    }
    }
    

    Activity Class

    package com.som_itsolutions.training.java.exampleeventlistener;

    public class Activity implements Widget.OnClickEventListener
    {
        public Button mButton;
        public CheckBox mCheckBox;
        private static Activity mActivityHandler;
        public static Activity getActivityHandle(){
            return mActivityHandler;
        }
        public Activity ()
        {
            mActivityHandler = this;
            mButton = new Button();
            mButton.setOnClickEventListner(this);
            mCheckBox = new CheckBox();
            mCheckBox.setOnClickEventListner(this);
            } 
        public void onClick (Widget source)
        {
            if(source == mButton){
                mButton.setButtonText("Thank you for clicking me...");
                System.out.println(((Button) mButton).getButtonText());
            }
            if(source == mCheckBox){
                if(mCheckBox.isChecked()==false){
                    mCheckBox.setCheck(true);
                    System.out.println("The checkbox is checked...");
                }
                else{
                    mCheckBox.setCheck(false);
                    System.out.println("The checkbox is not checked...");
                }       
            }
        }
        public void doSomeWork(Widget source){
            source.clickEvent();
        }   
    }
    

    Other Class

    public class OtherClass implements Widget.OnClickEventListener{
    Button mButton;
    public OtherClass(){
    mButton = Activity.getActivityHandle().mButton;
    mButton.setOnClickEventListner(this);//interested in the click event                        //of the button
    }
    @Override
    public void onClick(Widget source) {
    if(source == mButton){
    System.out.println("Other Class has also received the event notification...");
    }
    }
    

    Main Class

    public class Main {
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    Activity a = new Activity();
    OtherClass o = new OtherClass();
    a.doSomeWork(a.mButton);
    a.doSomeWork(a.mCheckBox);
    }
    }
    

    As you can see from the above code, that we have an interface called events which basically lists all the events that may happen for our application. The Widget class is the base class for all the UI components like Button, Checkbox. These UI components are the objects that actually receive the events from the framework code. Widget class implements the Events interface and also it has two nested interfaces namely OnClickEventListener & OnLongClickEventListener

    These two interfaces are responsible for listening to events that may occur on the Widget derived UI components like Button or Checkbox. So if we compare this example with the earlier Callback example using Java Interface, these two interfaces work as the Callback interface. So the higher level code (Here Activity) implements these two interfaces. And whenever an event occurs to a widget, the higher level code (or the method of these interfaces implemented in the higher level code, which is here Activity) will be called.

    Now let me discuss the basic difference between Callback and Eventlistener pattern. As we have mentioned that using Callback, the Callee can notify only a single Caller. But in the case of EventListener pattern, any other part or class of the Application can register for the events that may occur on the Button or Checkbox. The example of this kind of class is the OtherClass. If you see the code of the OtherClass, you will find that it has registered itself as a listener to the ClickEvent that may occur in the Button defined in the Activity. Interesting part is that, besides the Activity ( the Caller), this OtherClass will also be notified whenever the click event occurs on the Button.

    0 讨论(0)
  • 2020-11-22 11:39

    A callback is a method that is scheduled to be executed when a condition is met.

    An "real world" example is a local video game store. You are waiting for Half-Life 3. Instead of going to the store every day to see if it is in, you register your email on a list to be notified when the game is available. The email becomes your "callback" and the condition to be met is the game's availability.

    A "programmers" example is a web page where you want to perform an action when a button is clicked. You register a callback method for a button and continue doing other tasks. When/if the user cicks on the button, the browser will look at the list of callbacks for that event and call your method.

    A callback is a way to handle events asynchronously. You can never know when the callback will be executed, or if it will be executed at all. The advantage is that it frees your program and CPU cycles to perform other tasks while waiting for the reply.

    0 讨论(0)
提交回复
热议问题