JavaScript 回调函数

158 阅读9分钟

JavaScript 回调函数

JavaScript 中的回调函数是在第一个函数完成其任务后调用的函数。详细了解它们的使用方式和使用时机。

回调函数是JavaScript中的一个函数,在第一个函数完成其任务后由第一个函数调用(或调用)。它是一个从另一个函数接收输入的函数。

回调通常用于处理网络请求或文件 I/O等异步事件。这是一种保证在给定任务完成之前不会运行某些代码的方法。回调可以成为异步编程的有效工具。它们使您可以选择将执行异步操作的代码与处理此类操作结果的代码分开。

JavaScript 回调函数详解

回调函数是在第一个函数完成其任务后调用的函数。它们通常用于处理异步事件并使您的代码更具可读性。

这可以使您的代码更加模块化和易于理解。我将解释如何使用回调函数以及何时使用它们。

什么是回调函数?

回调函数是在第一个函数完成其任务后部署的函数。它们经常部署在管理异步操作(例如从服务器检索数据、处理事件和确保正确的操作顺序)等场景中。
例如,Node.jssetTimeout和浏览器中的方法在调用函数之前会等待指定的毫秒数,一秒等于一千毫秒。

image.png

一般来说,等待并不是一项非常重要的工作,尽管在执行更新动画或确定任何事情是否花费的时间比预期的要长等任务时它会有所帮助。

当使用回调连续执行多个异步操作时,必须不断发送新函数来处理操作后的计算继续。

为什么 JavaScript 中的回调函数很重要?

回调函数在 JavaScript 中非常重要,因为它们允许您创建不会阻塞主执行线程的异步代码。这样,您可以在执行异步操作的同时执行其他任务,例如用户界面 (UI)更新或其他API 调用。

JavaScript 回调函数很重要,原因如下:

  • • 它们允许您处理事件。JavaScript 程序中的事件包括用户按下按钮或网络请求结束等事件。回调允许在事件发生时对其进行处理。
  • • 您可以使用它们发送异步 API 调用。  许多 API 都是异步的,这意味着它们不会立即返回值。它们会返回一个承诺或回调方法。当API 调用完成时,将调用回调函数。
  • • 您可以使用它们来增强代码的性能。  回调使您可以在异步操作运行时执行多任务,这可以帮助您的代码执行得更快。
  • • 回调函数可用于管理异步操作流程,从而防止臭名昭著的“回调地狱”。  在这种情况下,深度嵌套的回调会使代码难以阅读和维护。
  • • **闭包允许函数“记住”生成它们的作用域,回调函数经常使用闭包。**闭包在保存状态和封装行为方面非常有效。
  • • 高阶函数,即可以将其他函数作为输入或将其他函数作为值返回的函数,是基于回调的概念的。  这种函数式编程模式非常有效。

何时使用回调函数

当您需要在异步过程完成后采取行动时,回调会很有帮助。例如,您可以利用回调函数来:

  • • 网络请求完成后更新 UI。
  • • 读取文件后处理数据。
  • • 收到第一次 API 调用的结果后,进行另一次 API 调用。

当您想将执行异步操作的代码与处理操作结果的代码分开时,通常应使用回调函数。这样您的代码可能会变得更加模块化且更易于理解。

回调函数还可以改善错误处理,并在异步过程中发生错误时允许温和降级。您可以通过将结果或错误的处理封闭在回调中来有效地控制程序的流程,确保它能够正确响应各种结果而不会干扰整个应用程序的功能。

以下是您可能需要使用回调函数的一些特定情况:

  • • 进行异步 API 调用时。
  • • 当监听事件时。
  • • 运行长时间运行的任务时。
  • • 当处理承诺时。

例如,回调函数可用于在网络请求完成后更新 UI:

image.png 此示例中的按钮使用方法添加了一个事件侦听器addEventListener()。单击按钮时,event listener将激活名为的回调函数。然后回调函数会异步访问/api/users端点。API 调用完成后,回调函数会使用用户的数据更新 UI。

同步与异步回调函数

同步回调函数立即执行,但异步回调函数稍后执行。

执行同步回调时会遵循定义的顺序。这意味着,如果一个函数调用两个同步回调,则第一个回调将先于第二个回调处理。异步回调的执行顺序是随机的。因此,您无法预测何时会调用异步回调。

当需要立即执行某些操作(例如更新用户界面或调用API)时,经常使用同步回调。当您需要执行需要一些时间的任务(例如读取文件或发送网络请求)时,经常使用异步回调。由于同步回调遵循顺序流程,因此更容易理解。但是,在活动时间较长的情况下,它们可能会导致行为阻塞。

对于管理需要时间的任务(例如网络请求),异步回调至关重要。它们允许程序在等待这些操作完成的同时执行其他任务,从而提高应用程序的响应速度和效率。让我们看一个同步和异步函数的示例。

同步回调

在此示例中,我们有两个函数:greetsayGoodbye。该greet函数接受两个参数:(name一个字符串)和callback(一个函数)。它使用提供的名称记录问候消息,然后调用回调函数。

sayGoodbye函数只是记录一条"Goodbye!"消息。

image.png

当我们调用时greet("Alice", sayGoodbye),它将输出:

image.pngsayGoodbye函数在函数完成后立即被调用greet,这使其成为同步回调函数的一个示例。回调函数的异步执行意味着它在运行下一行代码之前被调用并完成。

异步回调

本例中,该asyncOperation函数用来setTimeout模拟异步任务,延迟1秒后执行回调。

image.png

输出:

image.png

JavaScript 中的回调函数示例

以下是 JavaScript 中回调函数的一些示例:

设置超时()

setTimeout()以回调函数作为参数,并在指定的时间后执行回调函数。

它需要两个参数:第一个是需要执行的回调函数,第二个是调用回调函数之前的时间延迟(以毫秒为单位)。

在给定的示例中,如果将其设置setTimeout()为 1000 毫秒(或 1 秒),则意味着提供的回调函数将在 1 秒后执行。

image.png

添加事件监听器()

此函数有两个参数:事件名称和回调函数。回调函数在事件发生时执行。

在此示例中,querySelector('button')选择文档中的第一个“”元素。后续addEventListener函数为此按钮上的事件添加事件监听器"click"。当单击按钮时,将执行提供的回调函数,"Button clicked!"并与事件对象一起记录到控制台。

image.png

Promise.then()

该方法以回调函数作为参数,并在承诺得到解决时执行回调函数。在这个例子中,我们创建一个Promise (myPromise)使用 来模拟异步操作的setTimeout。在 中Promise,经过一秒钟的延迟后,我们Promise用消息解析'The promise was resolved!'。然后我们将一个then()方法链接到myPromise。 的第一个参数then()是一个函数,如果 被解析,它将被执行Promise

image.png

异步/等待

JavaScript 中的异步编程通常需要构建和管理Promises,这会导致代码复杂且难以阅读。Asyncawait是 JavaScript 为简化此过程而引入的两个关键字。在此示例中,这是一个名为的异步函数fetchData。它负责从指定的API 端点]获取数据。在函数内部,它使用一个try...catch块来处理获取操作期间可能发生的任何潜在错误。它用于await暂停函数的执行,直到获取操作完成。这样,您就可以在结果可用时使用它。响应以对象的形式获得Response,需要将其转换为JSON才能response.json()提取实际数据。此示例演示了如何async简化await异步代码,使其看起来更像同步代码。关键字允许您以更直接和线性的方式await使用。Promises

image.png

解决回调函数的常见问题以下是一些常见的回调函数问题及处理方法:

  • • 未调用回调函数。  如果回调函数定义不正确或未提供给适当的函数,则可能会发生这种情况。确保回调函数定义正确并且正确的函数接收它。
  • • 回调函数调用得太晚。  如果异步操作已经结束,则可能会发生这种情况。确保在异步操作结束后调用回调函数。
  • • 回调函数调用过早。  如果异步操作尚未完成,则可能会发生这种情况。在异步操作完成之前,请勿调用回调函数。
  • • 忘记传递回调函数。  调用需要回调函数的函数时,请仔细检查是否确实提供了该函数。确保回调参数存在于函数签名中。通过两次检查函数调用,确保回调作为参数提供。
  • • 错误处理。  如果您使用的回调函数处理错误,请确保它彻底筛查并响应可能出现的任何问题。确保回调函数具有管理错误的正确逻辑,例如查找错误对象并正确处理它们。
  • • 调试。有时,问题可能不是出在回调函数上,而是出在代码的其他部分。要分析变量并跟踪执行路径,请使用命令、断点和浏览器开发人员工具等 调试工具。