Heim >Web-Frontend >js-Tutorial >Detaillierte Erläuterung der Callback-Funktionen in JavaScript
JavaScript Callback Funktionen sind ein wichtiges Konzept, das Sie verstehen müssen, um ein erfolgreicher JavaScript-Entwickler zu sein. Aber ich glaube, dass Sie nach der Lektüre dieses Artikels in der Lage sein werden, alle Hindernisse zu überwinden, mit denen Sie vor der Verwendung von Rückrufmethoden konfrontiert waren.
Bevor wir beginnen, müssen wir zunächst sicherstellen, dass unser Verständnis der Funktionen solide ist.
Eine Funktion ist ein logischer Baustein mit einer Reihe von Code darin, um eine bestimmte Aufgabe auszuführen. Mit Funktionen können Sie Code tatsächlich besser organisiert schreiben, um das Debuggen und die Wartung zu vereinfachen. Funktionen ermöglichen auch die Wiederverwendung von Code.
Sie müssen die Funktion nur einmal definieren und bei Bedarf aufrufen, anstatt immer wieder denselben Code zu schreiben.
Nun sehen wir uns an, wie man eine Funktion in Javascript deklariert.
Verwendung des Funktionskonstruktors: Bei dieser Methode wird die Funktion mit Hilfe des Konstruktors „Funktion“ erstellt. Technisch gesehen ist diese Methode weniger effizient als die Verwendung der Funktionsausdruckssyntax und der Funktionsdeklarationsanweisungssyntax zum Deklarieren von Funktionen.
Verwenden Sie Funktionsausdrücke: Normalerweise ist diese Methode dieselbe wie die Variablenzuweisung. Kurz gesagt, der Funktionskörper wird als Ausdruck behandelt und dieser Ausdruck wird einer Variablen zugewiesen. Mit dieser Syntax definierte Funktionen können benannte oder anonyme Funktionen sein.
Eine Funktion ohne Namen wird als anonyme Funktion bezeichnet. Eine anonyme Funktion ist selbstaufrufend, das heißt, sie ruft sich automatisch selbst auf. Dieses Verhalten wird auch als sofort aufgerufener Funktionsausdruck (IIFE) bezeichnet.
Im Funktionskörper muss die Funktion einen Wert an den Aufrufer zurückgeben. Die Funktion wird nicht mehr ausgeführt, wenn eine Return-Anweisung auftritt. Innerhalb der Funktion fungieren Parameter als lokale Variablen.
In ähnlicher Weise sind Variablen, die innerhalb einer Funktion deklariert werden, lokale Variablen dieser Funktion. Auf lokale Variablen kann nur innerhalb dieser Funktion zugegriffen werden, sodass Variablen mit demselben Namen problemlos in verschiedenen Funktionen verwendet werden können.
Die zuvor deklarierte Funktion wird in einer der folgenden Situationen aufgerufen:
()
ruft diese Funktion auf. ()
运算符调用该函数。
按照 MDN 的描述:回调函数是作为参数传给另一个函数的函数,然后通过在外部函数内部调用该回调函数以完成某种操作。
让我用人话解释一下,回调函数是一个函数,将会在另一个函数完成执行后立即执行。回调函数是一个作为参数传给另一个 JavaScript 函数的函数。这个回调函数会在传给的函数内部执行。
在 JavaScript 中函数被看作是一类对象。对于一类对象,我们的意思是指数字、函数或变量可以与语言中的其他实体相同。作为一类对象,可以将函数作为变量传给其他函数,也可以从其他函数中返回这些函数。
可以执行这种操作的函数被称为高阶函数。回调函数实际上是一种模式。 “模式”一词表示解决软件开发中常见问题的某种行之有效的方法。最好将回调函数作为回调模式去使用。
客户端 JavaScript 在浏览器中运行,并且浏览器的主进程是单线程事件循环。如果我们尝试在单线程事件循环中执行长时间运行的操作,则会阻止该过程。从技术上讲这是不好的,因为过程在等待操作完成时会停止处理其他事件。
例如,alert
Lassen Sie es mich in menschlichen Begriffen erklären: Eine Callback-Funktion ist eine Funktion, die ausgeführt wird, sobald eine andere Funktion die Ausführung abschließt. Eine Callback-Funktion ist eine Funktion, die als Parameter an eine andere JavaScript-Funktion übergeben wird. Diese Rückruffunktion wird innerhalb der übergebenen Funktion ausgeführt.
🎜In JavaScript werden Funktionen als Objekttyp betrachtet. Mit einer Klasse von Objekten meinen wir, dass eine Zahl, Funktion oder Variable mit anderen Entitäten in der Sprache identisch sein kann. Als Objektklasse können Funktionen als Variablen an andere Funktionen übergeben und von anderen Funktionen zurückgegeben werden. 🎜🎜Funktionen, die diese Art von Operation ausführen können, werden als Funktionen höherer Ordnung bezeichnet. Rückruffunktionen sind eigentlich ein Muster. Das Wort „Muster“ bezieht sich auf einen bestimmten bewährten Ansatz zur Lösung häufiger Probleme in der Softwareentwicklung. Am besten verwenden Sie die Callback-Funktion als Callback-Muster. 🎜🎜Warum wir Rückrufe brauchen🎜🎜Client-JavaScript 🎜 läuft im Browser und der Hauptprozess des Browsers ist Single-Threaded Ereignisschleife🎜. Wenn wir versuchen, einen lang andauernden Vorgang in einer Single-Threaded-Ereignisschleife auszuführen, wird der Prozess blockiert. Technisch gesehen ist dies schlecht, da der Prozess die Verarbeitung anderer Ereignisse stoppt, während er auf den Abschluss des Vorgangs wartet. 🎜🎜Zum Beispiel gilt diealert
-Anweisung als einer der Blockierungscodes in Javascript im Browser. Wenn Sie eine Warnung ausführen, können Sie erst dann mit dem Browser interagieren, wenn Sie das Warnungsdialogfenster schließen. Um zu verhindern, dass lang laufende Vorgänge blockiert werden, verwenden wir Rückrufe. 🎜🎜Lassen Sie uns etwas tiefer gehen, damit Sie genau wissen, in welchen Fällen Rückrufe verwendet werden. 🎜🎜🎜🎜Im obigen Codeausschnitt wird zuerst die Funktion getMessage()
und dann die Funktion displayMessage()
ausgeführt. Beide zeigen eine Meldung im Konsolenfenster des Browsers an und beide werden sofort ausgeführt. getMessage()
函数,然后执行 displayMessage()
。两者都在浏览器的控制台窗口中显示了一条消息,并且都立即执行。
在某些情况下,一些代码不会立即执行。例如,如果我们假设 getMessage()
函数执行 API 调用,则必须将请求发送到服务器并等待响应。这时我们应该如何处理呢?
我认为与其告诉你 JavaScript 回调函数的语法,不如在前面的例子中实现回调函数更好。修改后的代码段显示在下面的截图中。
为了使用回调函数,我们需要执行某种无法立即显示结果的任务。为了模拟这种行为,我们用 JavaScript 的 setTimeout()
函数。该函数会暂停两秒钟,然后在控制台窗口中显示消息“ Hi,there”。
“显示的消息”将被显示在浏览器的控制台窗口中。在这种情况下,首先,我们需要等待 getMessage()
函数。成功执行此函数后,再执行 displayMessage()
函数。
让我解释一下前面的例子在幕后发生的事。
从上一个例子可以看到,在 getMessage()
函数中,我们传递了两个参数。第一个参数是 msg
变量,该变量显示在浏览器的控制台窗口中,第二个参数是回调函数。
现在,你可能想知道为什么将回调函数作为参数进行传递 —— 要实现回调函数,我们必须将一个函数作为参数传给另一个函数。
在 getMessage()
完成任务后,我们将调用回调函数。之后,当调用 getMessage()
函数时,将引用传给displayMessage()
函数,该函数就是回调函数。
注意,当调用 getMessage()
函数时,我们仅将其引用传给 displayMessage()
函数。这就是为什么你不会在它旁边看到函数调用运算符,也就是()
符号。
JavaScript 被认为是单线程脚本语言。单线程是指 JavaScript 一次执行一个代码块。当 JavaScript 忙于执行一个块时,它不可能移到下一个块。
换句话说,我们可以认为 JavaScript 代码本质上总是阻塞的。但是这种阻塞性使我们无法在某些情况下编写代码,因为在这些情况下我们没有办法在执行某些特定任务后立即得到结果。
我谈论的任务包括以下情况:
为了处理这些情况,必须编写异步代码,而回调函数是处理这些情况的一种方法。所以从本质上上说,回调函数是异步的。
当多个异步函数一个接一个地执行时,会产生回调地狱。它也被称为厄运金字塔。
假设你要获取所有 Github 用户的列表。然后在用户中搜索 JavaScript 库的主要贡献者。再然后,你想要在用户中获取姓名为 John 的人员的详细信息。
为了在回调的帮助下实现这个功能,代码应该如下所示:
http.get('https://api.github.com/users', function(users) { /* Display all users */ console.log(users); http.get('https://api.github.com/repos/javascript/contributors?q=contributions&order=desc', function(contributors) { /* Display all top contributors */ console.log(contributors); http.get('https://api.github.com/users/Jhon', function(userData) { /* Display user with username 'Jhon' */ console.log(userData); }); }); });
从上面的代码片段中,你可以看到代码变得更加难以理解,以及难以维护和修改。这是由回调函数的嵌套而引发的。
可以使用多种技术来避免回调地狱,如下所示。
让我们谈谈怎样用 async.js 库避免回调地狱。
根据 async.js 官方网站的描述:Async 是一个工具模块,它提供了直接、强大的函数来使用异步 JavaScript。
Async.js 总共提供约 70 个函数。现在,我们将仅讨论其中两个,即 async.waterfall()
和 async.series()
getMessage()
einen API-Aufruf ausführt, muss sie die Anfrage an den Server senden und auf die Antwort warten. Wie sollen wir damit umgehen? setTimeout()
. Die Funktion pausiert für zwei Sekunden und zeigt dann die Meldung „Hallo, da“ im Konsolenfenster an. 🎜🎜Die „angezeigte Nachricht“ wird im Konsolenfenster des Browsers angezeigt. In diesem Fall müssen wir zunächst auf die Funktion getMessage()
warten. Nachdem Sie diese Funktion erfolgreich ausgeführt haben, führen Sie die Funktion displayMessage()
aus. 🎜getMessage()
zwei Parameter. Der erste Parameter ist die Variable msg
, die im Konsolenfenster des Browsers angezeigt wird, und der zweite Parameter ist die Rückruffunktion. 🎜🎜Jetzt fragen Sie sich vielleicht, warum Callback-Funktionen als Parameter übergeben werden – um Callback-Funktionen zu implementieren, müssen wir eine Funktion als Parameter an eine andere Funktion übergeben. 🎜🎜Nachdem getMessage()
seine Aufgabe abgeschlossen hat, rufen wir die Rückruffunktion auf. Wenn später die Funktion getMessage()
aufgerufen wird, wird der Verweis an die Funktion displayMessage()
übergeben, bei der es sich um die Rückruffunktion handelt. 🎜🎜Beachten Sie, dass wir beim Aufruf der Funktion getMessage()
nur deren Referenz an die Funktion displayMessage()
übergeben. Aus diesem Grund wird der Funktionsaufrufoperator, das Symbol ()
, daneben nicht angezeigt. 🎜var async = require('async'); async.waterfall([ function(callback) { /* Here, the first argument value is null, it indicates that the next function will be executed from the array of functions. If the value was true or any string then final callback function will be executed, other remaining functions in the array will not be executed. */ callback(null, 'one', 'two'); }, function(param1, param2, callback) { // param1 now equals 'one' and param2 now equals 'two' callback(null, 'three'); }, function(param1, callback) { // param1 now equals 'three' callback(null, 'done'); } ], function (err, result) { /* This is the final callback function. result now equals 'done' */ });🎜 Aus dem obigen Codeausschnitt können Sie ersehen, dass der Code schwieriger zu verstehen sowie schwieriger zu warten und zu ändern ist. Dies wird durch die Verschachtelung von Callback-Funktionen verursacht. 🎜
async.waterfall()
und async.series()
. 🎜🎜async.waterfall()🎜🎜Diese Funktion ist sehr nützlich, wenn Sie bestimmte Aufgaben nacheinander ausführen und dann die Ergebnisse der vorherigen Aufgabe an die nächste übergeben möchten. Es benötigt ein „task“-Array von Funktionen und eine letzte „Callback“-Funktion, die aufgerufen wird, nachdem alle Funktionen im „task“-Array abgeschlossen sind oder nachdem der „callback“ mit einem Fehlerobjekt aufgerufen wurde. 🎜var async = require('async'); async.waterfall([ function(callback) { /* Here, the first argument value is null, it indicates that the next function will be executed from the array of functions. If the value was true or any string then final callback function will be executed, other remaining functions in the array will not be executed. */ callback(null, 'one', 'two'); }, function(param1, param2, callback) { // param1 now equals 'one' and param2 now equals 'two' callback(null, 'three'); }, function(param1, callback) { // param1 now equals 'three' callback(null, 'done'); } ], function (err, result) { /* This is the final callback function. result now equals 'done' */ });
当你要运行一个函数然后在所有函数成功执行后需要获取结果时,它很有用。 async.waterfall()
和 async.series()
之间的主要区别在于, async.series()
不会将数据从一个函数传递到另一个函数。
async.series([ function(callback) { // do some stuff ... callback(null, 'one'); }, function(callback) { // do some more stuff ... callback(null, 'two'); } ], // optional callback function(err, results) { // results is now equal to ['one', 'two'] });
用技术术语来说,闭包是捆绑在一起的函数的组合,引用了其周围的状态。
简而言之,闭包允许从内部函数访问外部函数的作用域。
要使用闭包,我们需要在一个函数内部定义另一个函数。然后,我们需要将其返回或传给另一个函数。
从概念上讲,回调类似于闭包。回调基本上是把一个函数作为另一个函数的用法。
希望本文能消除你对 javascript 回调函数的所有疑问。如果你觉得这篇文章有帮助,请与他人分享。
原文地址:https://dzone.com/articles/javascript-callback-functions-in-depth-guide-for-2
为了保证的可读性,本文采用意译而非直译。
更多编程相关知识,请访问:编程教学!!
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Callback-Funktionen in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!