如何用简单的英语解释回调?它们与从一个函数调用另一个函数从调用函数获取上下文有什么不同?如何向新手程序员解释它们的强大功能?


当前回答

回调函数:

我们定义了一个名为callback的回调函数,给它一个参数otherFunction,并在函数体中调用它。

function callback(otherFunction){
    otherFunction();
}

当我们调用回调函数时,它需要一个类型为函数的参数,因此我们使用匿名函数调用它。但是,如果实参不是function类型,则会产生错误。

callback(function(){console.log('SUCCESS!')}); 
callback(1); // error

烤披萨的例子。 烤炉 披萨底,上面有配料 这里,烤箱是回调函数。 披萨的配料是另一个功能。

值得注意的是,不同的披萨原料可以做出不同类型的披萨,但烘焙披萨的烤箱是一样的。 这在某种程度上是回调函数的工作,它不断期望具有不同功能的函数,以产生不同的自定义结果。

其他回答

回调是在满足条件时被计划执行的方法。

一个“真实世界”的例子是当地的电子游戏商店。你在等待《半条命3》。你不必每天去商店查看游戏是否上架,而是在列表中注册电子邮件,以便在游戏上架时收到通知。这封邮件变成了你的“回调”,你需要满足的条件是游戏的可用性。

“程序员”的例子是一个网页,你想在点击按钮时执行一个操作。为按钮注册回调方法,然后继续执行其他任务。当/如果用户点击按钮,浏览器将查看该事件的回调列表并调用您的方法。

回调是一种异步处理事件的方法。你永远不知道回调什么时候会被执行,或者它是否会被执行。这样做的好处是可以释放程序和CPU周期,以便在等待应答时执行其他任务。

什么是回调函数?

对第一个问题的简单回答是,回调函数是通过函数指针调用的函数。如果你将一个函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用它所指向的函数时,就被称为回调。

回调函数很难跟踪,但有时它非常有用。尤其是在设计库的时候。回调函数就像让你的用户给你一个函数名,你会在一定条件下调用这个函数。

例如,您编写了一个回调计时器。它允许您指定持续时间和调用什么函数,函数将相应地被回调。“每10秒运行myfunction() 5次”

或者,您可以创建一个函数目录,传递一个函数名列表,并要求库进行相应的回调。"如果成功,回调成功(),如果失败,回调失败()。"

让我们看一个简单的函数指针的例子

void cbfunc()
{
     printf("called");
}

 int main ()
 {
                   /* function pointer */ 
      void (*callback)(void); 
                   /* point to your callback function */ 
      callback=(void *)cbfunc; 
                   /* perform callback */
      callback();
      return 0; 
}

如何传递参数回调函数?

注意到实现回调的函数指针接受void *,这表明它可以接受任何类型的变量,包括结构。因此,您可以通过结构传递多个参数。

typedef struct myst
{
     int a;
     char b[10];
}myst;

void cbfunc(myst *mt) 
{
     fprintf(stdout,"called %d %s.",mt->a,mt->b); 
}

int main() 
{
       /* func pointer */
    void (*callback)(void *);       //param
     myst m;
     m.a=10;
     strcpy(m.b,"123");       
     callback = (void*)cbfunc;    /* point to callback function */
     callback(&m);                /* perform callback and pass in the param */
     return 0;   
}

假设你需要一个函数返回10的平方,那么你写一个函数:

function tenSquared() {return 10*10;}

之后你需要9的平方,所以你写了另一个函数:

function nineSquared() {return 9*9;}

最终你将用一个泛型函数替换所有这些:

function square(x) {return x*x;}

同样的想法也适用于回调。你有一个函数,它做一些事情,当完成时调用doA:

function computeA(){
    ...
    doA(result);
}

之后你想要完全相同的函数调用doB,而不是你可以复制整个函数:

function computeB(){
    ...
    doB(result);
}

或者你可以将回调函数作为变量传递,并且只需要使用该函数一次:

function compute(callback){
    ...
    callback(result);
}

然后你只需要调用compute(doA)和compute(doB)。

除了简化代码之外,它还让异步代码通过在完成时调用任意函数来让您知道它已经完成,这与打电话给某人并留下回调号码类似。

在PHP中,它是这样的:

<?php

function string($string, $callback) {
     $results = array(
        'upper' => strtoupper($string),
        'lower' => strtolower($string),
        );

    if(is_callable($callback)) {
        call_user_func($callback, $results);
    }
}

string('Alex', function($name) {
    echo $name['lower'];
});

用电话系统来描述回调是最容易的。函数调用类似于打电话给某人,问她一个问题,得到答案,然后挂断电话;添加回调改变了这个类比,这样在问她一个问题之后,你也可以告诉她你的名字和电话号码,这样她就可以给你回电话,告诉你答案。——保罗·雅库比 、《c++中的回调实现》