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


当前回答

如果没有回调或其他特殊的编程资源(如线程等),程序就是一个指令序列,一个接一个地按顺序执行,即使具有某种由某些条件决定的“动态行为”,所有可能的场景都必须预先编程。

因此,如果我们需要为程序提供一个真正的动态行为,我们可以使用回调。通过回调,你可以通过参数指令,一个程序调用另一个程序,提供一些先前定义的参数,并可以期望一些结果(这是契约或操作签名),因此这些结果可以由之前不知道的第三方程序产生/处理。

这种技术是应用于计算机运行的程序、函数、对象和所有其他类型代码的多态的基础。

以回调为例的人类世界很好地解释了当你在做一些工作时,假设你是一个画家(这里你是主程序,负责绘画),有时会打电话给你的客户,请他批准你的工作结果,所以,他决定图片是否好(你的客户是第三方程序)。

在上面的例子中,你是一个画家,并“委托”给其他人的工作来批准结果,图片是参数,每个新的客户端(回调的“函数”)改变你的工作结果,决定他想要的图片(客户端做出的决定是“回调函数”返回的结果)。

我希望这个解释对你有用。

其他回答

这是关于下载网页的:

Your program runs on a cellphone and is requesting the webpage http://www.google.com. If you write your program synchronously, the function you write to download the data will be running continuously until all the data is download. This means your UI will not refresh and will basically appear frozen. If you write your program using callbacks, you request the data and say "execute this function when you've finished." This allows the UI to still allow user interaction while the file is downloading. Once the webpage has finished downloading, your result function (callback) is called and you can handle the data.

基本上,它允许你请求一些东西,并在等待结果的同时继续执行。一旦结果通过回调函数返回给您,您就可以从它停止的地方开始操作。

程序员Johny需要一个订书机,所以他去办公用品部门要了一个,填写完申请表后,他可以站在那里等着店员去仓库里找订书机(就像一个阻塞函数调用),或者去做其他的事情。

由于这通常需要时间,johny在申请表格上写了一张便条,要求他们在订书机准备好取书时给他打电话,这样他就可以去做其他事情,比如在办公桌上打盹。

说白了,回调就是承诺。乔、简、大卫和萨曼莎拼车去上班。乔今天开车。简,大卫和萨曼莎有几个选择:

每五分钟查看一下窗户,看看乔是否出去了 继续做他们的事,直到乔按门铃。

选项1:这更像是一个轮询示例,Jane将被困在一个“循环”中,检查Joe是否在室外。在此期间简不能做其他事情。

选项2:这是回调示例。简告诉乔当他在外面时按她的门铃。她给了他一个按门铃的“功能”。Joe不需要知道门铃是如何工作的,也不需要知道它在哪里,他只需要调用那个函数,即当他在那里时按门铃。

回调是由“事件”驱动的。在这个例子中,“事件”是乔的到来。例如,在Ajax中,事件可以是异步请求的“成功”或“失败”,并且每个事件都可以有相同或不同的回调。

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.

希望有帮助!

回调函数是作为参数传递给另一个函数的函数(在某些时候使用)。

以下是一些函数:

def greeting(name):
    print("Hello " + name + "!")

def departing(name):
    print("Goodbye " + name + "!")

下面是一个函数(使用ourCallBack作为回调参数):

def promptForName(ourCallback):
    myName = input("Enter Name:")
    ourCallback(myName)

现在让我们使用一些回调!

promptForName(greeting) 
# Enter Name: 
# >Ed
# Hello Ed!

promptForName(departing) 
# Enter Name: 
# >Ed
# Goodbye Ed!

promptForName(greeting) 
# Enter Name: 
# >Guy
# Hello Guy!

我能够很快地扩展我的代码。


处理(错误和误导性的)答案:

回调并不意味着异步!

JS在2015年得到承诺,async/await在2017年得到承诺。在此之前,使用回调。

这就是为什么这里的一些答案没有意义,他们把两者混为一谈了!

它们通常用于异步代码,但我的示例是同步的。

回调并不意味着事件驱动!

它们通常用于事件处理,但我的示例不是事件。

回调并不意味着闭包!

虽然通常用作提供闭包的一种简洁方式,但我的示例并不是这样。

回调不是第一类函数的完整定义!

它是创建第一类函数定义的众多特性之一。

C语言可以使用函数指针作为回调函数,尽管它没有第一类函数。

这里有两点需要解释,一个是回调是如何工作的(传递一个可以在不了解上下文的情况下调用的函数),另一个是它的用途(异步处理事件)。

用其他答案用过的等待包裹到达的比喻来解释这两个问题是很好的。在计算机程序中,你会告诉计算机期待一个包裹。通常情况下,它现在会坐在那里等待(什么也不做),直到包裹到达,如果包裹从未到达,它可能会无限期地等待。对人类来说,这听起来很愚蠢,但如果没有进一步的措施,这对计算机来说是完全自然的。

现在回调是你前门的铃声。你为包裹服务提供了一种通知你包裹到达的方式,而不需要他们知道你在房子的哪里(即使),或者铃声是如何工作的。(例如,一些“铃声”实际上是发送一个电话。)因为你提供了一个“回调函数”,可以在任何时候被“调用”,脱离上下文,你现在可以不用坐在门廊前,随时“处理事件”(包裹到达)。