译文:JS回调函数深度指南
共 4004字,需浏览 9分钟
·
2022-03-18 02:29
我是法医,一只治疗系前端码猿🐒,与代码对话,倾听它们心底的呼声,期待着大家的点赞👍与关注➕,当然也欢迎加入前端猎手技术交流群😛,文末扫码我拉你进群,一起交流技术以及代码之外的一切🙆♀️
转载自Duing(ID:duyi-duing)
原文链接:https://dev.to/nileshsanyal/javascript-callback-functions-in-depth-guide-for-2019-gj7
作者:Nilesh Sanyal
如有翻译不准,请多指正。
JS回调函数是你必须了解的重要概念,否则,在成为一名成功的前端开发工程师可能会面临很多障碍。但我相信,在彻底阅读本文之后,您将能够克服以前在回调方面遇到的任何困难。
本文我将分享关于回调函数的很多技巧。但首先,你需要对函数有一些基本的认识。我的意思是你至少应该知道什么是函数,它是如何工作的,什么是不同类型的函数等等。
什么是函数?
函数是一个逻辑构建块,其中编写了一组代码以执行特定任务。实际上,函数允许以更有条理的方式编写代码,这也易于调试和维护。函数还允许代码重用。
函数只需定义一次,就可以在需要时调用它,而不必一次又一次地编写相同的代码。
我们讨论了一下什么是函数,现在,让我们看看如何在JS中声明函数。
使用函数构造函数:
在此方法中,函数是在"函数"构造函数的帮助下创建的。从技术上讲,这种方法不如使用函数表达式语法和函数声明语句语法声明函数更高效。
使用函数表达式:
通常,此方法与变量赋值相同。简单来说,函数体被视为表达式,该表达式分配给变量。使用此语法定义的函数可以是命名函数,也可以是匿名函数。
没有名称的函数称为匿名函数。匿名函数是自我调用的,这意味着它会自动调用自己。此行为也称为立即调用的函数表达式 (IIFE)。
使用函数声明语句:
实际上,此方法是JS中常用的老方法。在这里,在关键字"函数"之后,您必须指定函数的名称。之后,如果函数接受多个参数或参数;你也必须要提到它们。尽管此部分是完全可选的。
在函数的主体中,函数必须向调用方反馈一个值。找到return语句后,该函数将停止执行。在函数内部,参数将充当局部变量。
此外,在函数内声明的变量将是该函数的本地变量。只能在该函数中访问局部变量,因此具有相同名称的变量可以轻松地用于不同的函数。
发生以下任一情况时,将调用之前被声明的函数:
例如,当事件发生时,用户单击按钮或用户从下拉列表中选择某个选项等。
当从JS代码调用函数时。
该函数也可以自动调用,这一点我们已经在匿名函数表达式中讨论过了。
()运算符调用该函数。
根据MDN:回调函数是作为参数传递给另一个函数的函数,然后在外部函数内部调用该函数以完成某种例程或操作。
我知道在阅读了这个技术定义之后,你会感到困惑,几乎无法理解什么是真正的回调函数。
让我用简单的词来解释一下,回调函数是一个函数,它将在另一个函数完成执行后立即执行。回调函数是作为参数传递给另一个JS函数的函数。该回调函数在它所传递到的函数内部执行。
在JS中,函数被视为一等对象。通过说一等对象(我们的意思是一个数字或一个函数或一个变量)可以被视为与语言中的任何其他实体相同。作为一个一等对象,我们可以将函数传递给其他函数,因为变量和函数也可以从其他函数返回。
可以执行此操作的函数称为高阶函数。回调函数实际上是一种模式。"模式"这个词意味着某种经过验证的方法来解决软件开发中的常见问题。因此,我们最好将回调函数的使用称为回调模式。
客户端JS在浏览器中运行,主浏览器进程是单个线程事件循环。如果我们尝试在单线程事件循环中执行长时间运行的操作,则该过程将被阻止。这在技术上是错误的,因为该进程在等待操作完成时会停止处理其他事件。
例如,"alert"语句被视为浏览器中JS中的阻塞代码之一。如果您运行警报;您无法再在浏览器中执行任何交互,直到关闭警报对话框窗口。为了防止阻塞长时间运行的操作,使用回调。
让我们深入探讨,以便您确切地了解在哪个方案中使用了回调。
在上面的代码片段中,getMessage()函数首先执行,然后执行displayMessage()。两者都在浏览器的控制台窗口中显示一条消息,并且都立即执行。
但在某些情况下,某些代码不会被立即执行。例如,如果我们假设getMessage()函数执行API调用,我们必须将请求发送到服务器并等待响应,那么我们将如何处理它?
很简单,为了处理这种情况,我们需要在JS中使用回调函数。
我认为与其告诉你JS回调函数的语法,尝试在前面的示例中实现回调函数会更好。代码段显示在下面的屏幕截图中。
为了使用回调函数,我们需要执行某种无法立即显示结果的任务。为了模拟这种行为,我们使用JS的setTimeout()函数。该函数将需要2秒钟才能在控制台窗口中显示消息"Hi,there"。
显示此消息后,浏览器的控制台窗口中将显示"Displayedmessage" 。因此,在这种情况下,首先我们正在等待getMessage()函数,在成功执行此函数后,我们将执行displayMessage()函数。
让我解释一下在前面的例子中,幕后实际发生了什么。
从前面的示例中可以看出,在getMessage()函数中,我们传递了两个参数;第一个参数是"msg"变量,它显示在浏览器的控制台窗口中,第二个参数是"回调"函数。
现在,您可能想知道为什么"回调"函数作为参数传递。这是因为要实现回调函数,我们必须将一个函数作为参数传递给另一个函数。
在getMessage()函数完成它的任务后,我们调用该 "callback()"函数。之后,当我们调用getMessage()函数时,我们传递了对"displayMessage()"函数的引用,该函数被视为回调函数。
请注意,当调用getMessage()函数时,我们只是传递对 "displayMessage"函数的引用。这就是为什么,你不会看到函数调用运算符,即旁边的"()"。
JS被认为是一种单线程脚本语言。术语"单线程"意味着JS一次执行一个代码块。当JS忙于执行一个块时,它不可能移动到下一个块。
换句话说,我们可以说JS代码本质上总是阻塞的。但是这种阻塞性质会妨碍我们在某些情况下编写代码,因为我们在运行某些特定任务后无法获得即时结果。
我说的是诸如以下之的任务。
向某个终结点发送API调用以获取数据。
发送网络请求以从远程服务器获取某些资源(例如,文本文件、图像文件、二进制文件等)。
为了处理这些情况,我们必须编写异步代码,回调函数是处理这些情况的一种方法。因此,回调函数本质上是异步的。
当多个异步函数一个接一个地执行时,就会发生回调地狱。它也被称为厄运金字塔。
假设您要获取所有github用户的列表,然后在您要搜索的用户中,仅搜索JS存储库的顶级贡献者。然后,在这些人中,您希望获得名为Jhon的人的详细信息。
要在回调的帮助下实现此功能,代码片段将如下所示。
从上面的代码片段中,您可以看到代码变得更难理解,更难维护,也更难修改。这是由于所有回调函数的嵌套而发生的。
可以使用多种技术来避免回调地狱,如下所示。
通过使用promise。
在异步的帮助下等待。
通过使用异步.js库。
我已经分享过,如何使用承诺以及异步等待如何有助于避免回调地狱。
通过使用async.js库
让我们来谈谈使用async.js库以避免回调地狱。
根据async的官方网站.js:Async是一个实用程序模块,它为使用异步JS提供了直接,强大的功能。
Async.js总共提供了近70个函数。现在,我们将只讨论其中两个,即async.waterfall()和async.series()。
async.waterfall()
当您想要一个接一个地运行某些任务,然后将结果从上一个任务传递到下一个任务时,它非常有用。它需要一个函数"任务"数组和一个最终的"回调"函数,该函数在"任务"数组中的所有函数都已完成或使用错误对象调用"回调"之后调用。
async.series()
当您想要运行函数,然后在所有函数成功执行后需要获取结果时,此函数非常有用。async.waterfall()和 async.series()之间的主要区别在于 async.series()不会将数据从一个函数传递到另一个函数。
闭包
用技术术语来说,闭包是将函数捆绑在一起并引用其周围状态的组合。
简单地说,闭包允许从内部函数访问外部函数的作用域。
要使用闭包,我们需要在另一个函数中定义一个函数。然后我们需要返回它或将其传递给另一个函数。
回调
从概念上讲,回调类似于闭包。回调基本上是一个函数接受另一个函数作为参数的地方。
RECOMMEND
很感谢小伙伴看到最后😘,如果您觉得这篇文章有帮助到您的的话不妨关注➕+点赞👍+收藏📌+评论📜,您的支持就是我更新的最大动力。
欢迎加入前端猎手技术交流群😛,文末扫码加我微信,我拉你进群,一起交流技术以及代码之外的一切🙆♀️