为什么在JavaScript中使用回调,它的优点是什么?

有人可以解释一下,为什么我们在JavaScript中使用回调? 我找到了一些例子,但它们可以通过使用普通函数来实现。 使用它的优点是什么? 我得到了“如何”使用它的答案,而不是“为什么和什么时候”需要使用它。

通常,我发现它在AJAX中使用。 在httpRequest.onreadystatechange 。 这与Java的多线程相似吗? 响应的听众如何以及在哪里? 异步编程类似于多线程吗?

在下面的代码中,控制流程如何:

function some_function(arg1, arg2, callback) {
  var my_number = Math.ceil(Math.random() * (arg1 - arg2) + arg2);
  callback(my_number);
  some_different_function_not_callback(arg1);
}
some_function(5, 15, function(num) {
   console.log("callback called! " + num);
});

从JQuery网站:

关于回调的特殊之处在于,在“父”之后出现的函数可以在回调执行之前执行“(ref:http://docs.jquery.com/Tutorials:How_jQuery_Works)

有人能用一个例子向我解释这一行吗?


主浏览器进程是单线程事件循环。 如果您在单线程事件循环中执行长时间运行的操作,则该过程将“阻塞”。 这很糟糕,因为该进程在等待操作完成时停止处理其他事件。 'alert'是少数拦截浏览器方法之一:如果您调用alert('test'),则不能再单击链接,执行jjax查询或与浏览器UI进行交互。

为了防止长时间运行的操作阻塞,XMLHttpRequest提供了一个异步接口。 在操作完成之后,您将它传递给一个回调函数,并在处理它时将它控制回主事件循环而不是阻塞。

没有理由使用回调,除非要将某些事件绑定到事件处理函数,否则您的操作可能会阻塞,因此需要异步编程接口。

这是一个很好的视频,更多地讨论浏览器中使用的事件循环,以及node.js中的服务器端。

编辑:从jQuery文档的复杂的线只是意味着回调异步执行,因为控制被切回到主事件循环。

parent_function(function () { console.log('Callback'); });
parent_doesnt_block(); // <-- function appears after "parent"
therefore_execution_continues();
// Maybe we get 'Callback' in the console here? or maybe later...
execution_still_continues();

不太像多线程...

只要您需要等待主JS代码外部的东西,就可以使用回调。 在浏览器中,这对AJAX使用很多,而在node.js中,它用于调用系统的每一件事(文件访问,网络访问,数据库请求等)。

假设你想每次用户点击一个按钮时触发一个Ajax请求。 现在让我们说ajax请求需要10秒才能完成。 然后用户在这10秒钟之前点击其中的10个按钮。 这会反复调用这样的函数:

var clicked = function() {
  doAjax('/some/path.json', function(result) {
    updatePageWith(result.widgets);
  });
};

这会在JS引擎中运行代码的时间足够长以提出请求。 然后在等待时闲置。 其他JS可以运行在这个时候,UI是完全流畅和互动的,一切都非常棒。 突然之间,所有10个请求都立即解决。 然后我们的回调被调用10次,就像魔术一样。

这是有效的,因为每次我们调用clicked()我们都在创建一个新的函数对象,并将它传递给doAjax()函数。 所以在内存中有10个独特的回调函数对象,每个都通过doAjax()函数绑定到特定的请求。 当请求返回时,它找到相关的回调对象并调用它。

这里的巨大优势在于,尽管javascript是单线程的,但您永远不会在等待时绑定该线程。 如果你的JS线程忙,它应该只是因为它正在积极运行代码。 因此,尽管JS是单线程的,但代码隐含地保持任意数量的任何类型的异步任务的状态是微不足道的。

回调的同步方法通常用于不同的目的。 像听众或代表一样。 就像告诉对象A在数据更改时回调一样。 虽然不是严格异步,但通常不会立即调用该回调。 相反,它会在稍后响应某种事件的用户操作而被调用。


由于正在执行的JavaScript是异步的,因此如果您在发出异步请求后只放置了任何旧功能,则可能会在原始请求完成之前调用它。 原始请求将在BEGINS(发出)后立即返回,而不是完成。

如果您需要对异步请求的结果进行处理,或者将请求连锁在一起,则需要回调以确保下一步在上一步完成之前不会开始。

链接地址: http://www.djcxy.com/p/80509.html

上一篇: Why use callback in JavaScript, what are its advantages?

下一篇: recursion elimination?