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

后端 未结 30 2133
时光说笑
时光说笑 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: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

提交回复
热议问题