在 Javascript 中,可以定义一个函数 X 并将其作为参数传递给另一个函数 Y。
这样的函数 X 称为回调函数。
您能否解释为什么在一些清晰的示例中使用回调函数很有用(例如发送一些带有演示的小提琴链接)?我可以看到一个有用之处,那就是代码可读性,但我对此不确定,因为带有回调的代码看起来更复杂。
唯一的用处是它在浏览器环境中的使用和AJAX中的异步执行?
其他 Javascript 实现(例如 Rhino)怎么样?回调在那里也有用吗?或者它们的有用性仅取决于 Javascript 的执行环境?
谢谢
In Javascript there is a possibility to define a function X and pass it as an argument to another function Y.
Such a function X is called a callback function
.
Could you explain why is useful to use callback functions in some clear examples (e.g. send some fiddle links with demonstration)? I can see one usefulness, it's code readability, but I'm not sure in this, because code with callbacks looks more complex.
The only usefulness is it's use in browser environment and asynchronous execution in AJAX?
What about another Javascript implementations (e.g. Rhino)? Are callbacks useful there as well? Or does their usefulness depend only on the environment where Javascript is executed?
thank you
发布评论
评论(5)
作为参数的回调
回调非常有用,因为它们允许您使用代码“配置”函数。
典型的例子是一个排序函数,它允许您指定自己的排序标准。我将使用一个函数,该函数根据某些条件返回数组的最小值,因为它比排序更简单,但它仍然可以很好地作为说明:
查看此代码运行。 它有什么问题?
问题是,虽然我们做了一些努力来创建一个可配置的
min
函数(它根据我们指定的任何属性找到最小值) ,它在一般意义上仍然相当有限,因为它只能根据一个单一属性找到最小值。如果我们的数据是这样的怎么办?
这不再是一个对象数组,而是一个格式化字符串数组。它具有与原始集合相同的数据,但结构不同。导致原来的
min
函数无法用来处理。现在我们可以编写另一个版本的
min
来使用字符串而不是对象,但这有点毫无意义(有无数种方法可以表示相同的数据)。对于一种特定情况,这可能是一种快速而肮脏的解决方案,但考虑一下库编写者的问题:他们如何编写一个对每个人都有用的函数,而不知道数据将如何构造每个案例?救援回调
简单:通过允许用户指定如何从数据中提取条件,使
min
函数更加强大。这听起来很像“给出函数代码以从数据中提取标准”,这正是我们要做的。min
将接受回调:查看此代码运行。
现在我们的代码终于可以重用了。我们可以轻松地将其配置为以最少的努力处理第一种数据和第二种类型的数据。
查看支持回调的函数处理两种类型的数据。这是我们获得极大灵活性的结果,因为允许用户以回调的形式提供代码作为我们函数的一部分运行。
异步编程中的回调 回调
的另一个主要用途是启用异步编程模型。这在您计划完成操作但不希望程序在操作完成之前停止运行的所有情况下都很有用。
为了实现这一点,您需要为该操作提供一个回调函数,并有效地告诉它:为我完成这项工作,完成后给我回电话。然后,您可以自由地继续做任何您喜欢的事情,因为您知道当结果可用时您指定的函数将运行。
这在使用 AJAX 的 Web 中最为明显:您向 Web 服务器发出请求,当收到响应时,您可以以某种方式对其进行操作。您不想当场等待响应,因为这可能需要很长时间(例如,如果存在连接问题),并且您不希望您的程序在这段时间里一直没有响应。
有关 AJAX 回调的示例,请参阅 jQuery
load
的文档功能。Callbacks as parameters
Callbacks are useful because they allow you to "configure" a function with code.
The archetypal example for this is a sorting function which allows you to specify your own sort criteria. I 'm going to use a function that returns the minimum value of an array based on some criteria because it's simpler than a sort, but it still will serve fine as an illustration:
See this code run. What is the problem with it?
The problem is that while we made some effort in order to create a configurable
min
function (it finds the minimum based on any property we specify), it's still pretty limited in the general sense because it can only find the minimum based on one single property.What if our data was like this?
This is no longer an array of objects, but an array of formatted strings. It has the same data as the original collections, but in a different structure. As a result, the original
min
function cannot be used to process it.Now we could write another version of
min
that works with strings instead of objects, but that would be kind of pointless (there are infinitely many ways to represent the same data). This might be OK as a quick and dirty solution for one particular case, but consider the problem of a library writer: how could they write one function useful to everyone, without knowing how the data will be structured in each case?Callbacks to the rescue
Simple: make the
min
function more powerful by allowing its user to specify how to extract the criteria from the data. This sounds very much like "giving the function code to extract the criteria from the data", which is what we are going to do.min
will accept a callback:See this code run.
Now at last our code is reusable. We can easily configure it to work both with the first and the second type of data with minimal effort.
See the callback-enabled function handle both types of data. This is the result of the extreme flexibility we gained as a result of allowing the user to provide code to run as part of our function, in the form of a callback.
Callbacks in asynchronous programming
Another major use of callbacks is to enable asynchronous programming models. This is useful in all cases where you schedule an operation to complete, but do not want your program to stop running until the operation has completed.
In order for this to work, you provide the operation with a callback function and effectively tell it: go do this work for me, and when you are done, call me back. You are then free to go ahead and do anything you like, knowing that when the results are available the function you specified will run.
This is most visible in the web with AJAX: you fire off a request to a web server, and when the response has been received you act upon it in some manner. You don't want to wait on the spot for the response because it might take a lot of time (e.g. if there are connection problems) and you don't want your program to be unresponsive for all that time.
For an example of an AJAX callback, see the documentation for the jQuery
load
function.在 JavaScript 中,大量函数调用是异步的(例如使用 XMLHTTPRequest 执行 AJAX 请求)。因此,您不知道返回值何时到达,因为您的浏览器会在后台执行其他操作。
回调函数的概念允许您在异步调用完成执行其需要执行的操作后立即运行过程,而不会导致脚本的其余部分停止运行。
例如,假设我正在从某处请求
foo.json
。我会做类似的事情(虚构代码):当
ajaxGet
检索到时,回调函数 (function(data) { ... }
) 将自行执行数据,现已准备就绪。在此之前,doSomethingElse()
将执行并且不会挂起浏览器。为了回答您关于其他 JavaScript 环境的问题,让我们看一下 Node.js,它可以说是最流行的环境。
现在,node.js 是完全异步的,这意味着函数调用永远不会阻塞(理论上),因此您必须有回调来调用回调来执行任何类型的异步 I/O。事实上,我想说 Node.js 几乎是真正的连续传递风格,其中函数不返回并依赖回调来向前传递它们的值。
In JavaScript, a great deal of function calls are asynchronous (for instance using
XMLHTTPRequest
to perform AJAX requests). As such, you don't know when the return value will arrive, as your browser us executing something else in the background.Without causing the rest of your script to stop running, the notion of a callback function allows you to run a procedure as soon as an asynchronous call has finished performing what it needs to do.
For instance, suppose I'm requesting
foo.json
from somewhere. I would do something like (fictional code):The callback function will (
function(data) { ... }
) will execute of its own accord whenajaxGet
has retrieved the data and is now ready. Before that,doSomethingElse()
will execute and not hang the browser.To answer your question regarding other JavaScript environments, let's look at node.js, arguably the most popular one there is.
Now, node.js is fully asynchronous, meaning that function calls never block (theoretically) and therefore you're going to have to have callbacks that call callbacks for performing any kind of asynchronous I/O. In fact, I would say node.js is almost bona fide continuation-passing style, where functions don't return and rely on callbacks to pass their values forward.
自 AJAX 以来,回调在 JavaScript 中非常流行。 AJAX 是对另一个 Web 资源的异步调用,因为您不知道它何时完成,所以应用程序不需要等待响应。相反,它会继续执行,并且您提供一个回调,以便在请求完成后立即调用。
这个简单的代码提供了回调,以显示从服务器检索的产品:
此外,由于 JavaScript 本质上是函数式语言,因此函数在这里发挥着重要作用。您将函数传递给函数,或从函数返回函数。它对于不同的模式实现非常有用,例如
由于 JavaScript 函数性质和美观且简单的回调编程,它发现了它对 Node.js 等框架的影响,Node.js 是针对 IO 操作高度优化的 JavaScript 框架。
Node.js HelloWorld:
看,它创建 HTTP 服务器并为发送到该服务器的每个请求提供回调。您将发出响应并结束它。非常紧凑和高效的代码。
对于核心函数式编程,您可以看看这篇很棒的文章:
http://matt.might.net/articles/implementation-of-recursive-fixed-point-y-combinator-in-javascript-for-memoization/
Callbacks are highly popular in JavaScript since AJAX. AJAX is asynchonous call to another Web resouce, since you don't know when it is going to be finished, application don't need to wait for response. Instead, it continues exectution and you provide a callback to be called as soon as request is done.
This simple code provides callback, to show the products retrieved from server:
Moreover, due to JavaScript is functional language by nature functions have major role here. You are passing functions to functions, or returning functions from function. It is very useful for different patterns implementations, like
Because of JavaScript functional nature and goog-looking and easy callback programming it found its implications for frameworks like Node.js, which is javascript framework highly optimized on IO operations.
Node.js HelloWorld:
See, it creates HTTP server and provide callback for each request comming to that server. You will out the response and ends it. Very compact and efficient code.
For hardcore functional programming you might take a look this great article:
http://matt.might.net/articles/implementation-of-recursive-fixed-point-y-combinator-in-javascript-for-memoization/
如果您进行任何类型的事件监听,回调是不可避免的。 JavaScript 和事件驱动范式是兄弟。原因是网络浏览器中呈现的用户交互。
无论您是在 Node.js 中监听 DOM 事件、Ajax 完成、文件系统访问还是 HTTP 请求,您都必须定义一个在事件发生时调用的过程。
例如,更高级的回调形式是 promises。
此外,回调作为迭代处理器也很方便:
以下可以将所有字母替换为其代码点:
Callbacks are inevitable if you do any kind of event listening. JavaScript and event-driven paradigm are brothers in arms. User interaction as presented in web browsers is the reason.
Whether you listen to DOM events, Ajax completion, file system access or HTTP requests in Node.js, you must define a procedure to be called upon event occurring.
More advanced form of callbacks are promises, for instance.
Also, callbacks are handy as iteration processors:
The following could replace all letters with their code-points:
有助于异步函数调用。您可以调用回调并将其传递给异步函数并继续当前执行,而不是等待某些函数完成。一旦函数完成,它就会执行回调。 Ajax 使用回调。 这清楚地解释了 Ajax 如何使用回调。
这里有一些类似的线程。
为什么在 JavaScript 中使用回调,它的优点是什么?
我如何利用异步 XMLHttpRequest 的回调函数?
Helps for Asynchronous function calling. Rather than waiting some function completes you can call and pass the callback to an asynchronous function and continue the current execution. Once the function completes it execute the call back. Ajax uses callbacks. This explains how Ajax uses callbacks clearly.
Here are some similar threads.
Why use callback in JavaScript, what are its advantages?
How can I take advantage of callback functions for asynchronous XMLHttpRequest?