43

通过阅读一些文字,尤其是iOS文档中关于委托的内容,所有的协议方法都被称为自定义委托对象需要实现的钩子。但是其他一些书,将这些钩子命名为回调,它们之间有什么区别?它们只是名称不同但机制相同吗?除了 Obj-C 之外,其他一些编程语言,比如 C 也中了,和 Obj-C 的情况一样吗?

4

4 回答 4

35

这里的术语有点模糊。一般来说,两者都试图达到相似的结果。

通常,回调是您向 API 注册的函数(或委托),以便在处理流程中的适当时间调用(例如,通知您处理处于某个阶段)

钩子传统上意味着更通用的东西,用于修改对 API 的调用(例如修改传递的参数,监视调用的函数)。在这个意义上,它通常比 Java 等高级语言所能达到的水平低得多。

iOS的上下文中,钩子这个词的含义与上面的回调完全相同

于 2012-06-18T17:12:05.120 回答
19

让我加入一个 Javascript 答案。在 Javascript 中,回调钩子事件都被使用。按照这个顺序,它们都是比另一个更高层次的概念。

不幸的是,它们经常被不当使用,从而导致混乱。

回调

从控制流的角度来看,回调是一个函数,通常作为参数给出,您在从函数返回之前执行该函数。

这通常用于需要等待 I/O 的异步情况(例如 HTTP 请求、文件读取、数据库查询等)。您不想等待同步while循环,因此可以同时执行其他功能。

当您获取数据时,您(永久)放弃控制并使用结果调用回调。

function myFunc(someArg, callback) {
    // ...
    callback(error, result);
}

因为回调函数可能是一些尚未执行的代码,并且您不知道调用堆栈中函数上方的内容,所以通常不是抛出错误,而是将错误作为参数传递给回调。有错误优先结果优先的回调约定。

在 Javascript 世界中,大多数回调已被Promises取代,并且从 ES2017+ 开始,您可以本机使用async/await来摆脱富含回调的意大利面条式代码,并使异步控制流看起来像是同步的。

有时,在特殊的级联控制流中,您在函数中间运行回调。例如,在您运行的Koa(Web 服务器)中间件Redux 中间件next()中,它会在堆栈中的所有其他中间件都运行后返回。

挂钩

钩子并不是一个定义明确的术语,但在 Javascript 实践中,当您希望客户端(API/库用户、子类等)在控制流中定义明确的点采取可选操作时,您可以提供钩子。

因此,钩子可能是您在某个时间点调用的某个函数(例如,作为参数或类方法),例如在数据库更新期间:

data = beforeUpdate(data);

// ...update

afterUpdate(result);

通常的重点是:

  • 挂钩可以是可选的
  • 钩子通常是等待的,即它们在那里修改一些数据
  • 每个钩子最多调用一个函数(与事件相反)

React 在其Hooks API中使用了钩子,它们——引用它们的定义——“是让你“钩入”React 状态和生命周期特性的函数”,即它们让你改变 React 状态,并且每次在某些情况下运行自定义函数部分状态发生变化。

活动

在 Javascript 中,事件在特定时间点发出,客户端可以订阅它们。事件发生时调用的函数称为侦听器- 或者为了增加混淆,回调。我更喜欢避免使用“回调”这个词,而是使用“监听器”这个词。

这也是一种通用的 OOP 模式。

在前端有一个用于事件的DOM 接口,在 node.js 中有EventEmitter接口。在ReactiveX中实现了一个复杂的异步版本。

事件的属性:

  • 可能有多个侦听器/回调订阅(将执行)同一事件。
  • 它们通常不接收回调,只接收一些事件信息并同步运行
  • 通常,与 hooks 不同的是,它们不用于修改事件发射器控制流中的数据。发射器不在乎“是否有人在听”。它只是使用事件数据调用侦听器,然后立即继续。

示例:当数据流开始或结束、用户单击按钮或修改输入字段时发生事件。

于 2019-02-21T20:32:00.317 回答
14

这两个术语非常相似,有时可以互换使用。钩子是库中的一个选项,用户代码可以链接一个函数来改变库的行为。库函数不需要与用户代码同时运行;就像在析构函数中一样。

回调是一种特定类型的钩子,用户代码将在其中启动库调用,通常是 I/O 调用或 GUI 调用,它将控制权交给内核或 GUI 子系统。然后,控制进程在中断或信号上“回调”用户代码,以便用户代码可以提供处理程序。

从历史上看,我见过用于中断处理程序的钩子和用于 GUI 事件处理程序的回调。我还看到当例程是静态链接和动态代码中使用回调时使用的钩子。

于 2012-06-18T17:21:38.083 回答
4

已经有两个很好的答案,但我想再提供一个证据,术语“钩子”和“回调”是相同的,并且可以互换使用:FreeRTOS 支持“钩子”一词,但将“回调”视为等价词术语,当他们说:

空闲任务可以选择调用应用程序定义的挂钩(或回调)函数 - 空闲挂钩。

滴答中断可以选择调用应用程序定义的挂钩(或回调)函数 - 滴答挂钩。

由 heap_1.c、heap_2.c、heap_3.c、heap_4.c 和 heap_5.c 实现的内存分配方案可以选择包含一个 malloc() 失败挂钩(或回调)函数,该函数可以配置为在 pvPortMalloc() 时调用永远返回 NULL。

来源:https ://www.freertos.org/a00016.html

于 2018-06-08T17:27:33.230 回答