Har*_*rke 28 javascript jquery
有人可以解释一下,为什么我们在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);
});
Run Code Online (Sandbox Code Playgroud)
来自JQuery网站:
关于回调的特殊之处在于,在"父"之后出现的函数可以在回调执行之前执行"(参考:http://docs.jquery.com/Tutorials:How_jQuery_Works)
有人可以用一个例子向我解释这一行吗?
小智 20
主浏览器进程是单线程事件循环.如果在单线程事件循环中执行长时间运行的操作,则该进程会"阻塞".这很糟糕,因为进程在等待操作完成时停止处理其他事件.'alert'是为数不多的阻止浏览器方法之一:如果您调用alert('test'),则无法再单击链接,执行Ajax查询或与浏览器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();
Run Code Online (Sandbox Code Playgroud)
不太像多线程......
您可以在需要等待主JS代码外部的任何时候使用回调.在浏览器中,这用于AJAX,在node.js中,它用于调用系统的每一件事(文件访问,网络访问,数据库请求等).
假设您想在每次用户单击按钮时触发ajax请求.现在让我们说ajax请求需要10秒才能完成.然后用户在10秒钟之前点击其中的10个按钮.这会反复调用这样的函数:
var clicked = function() {
doAjax('/some/path.json', function(result) {
updatePageWith(result.widgets);
});
};
Run Code Online (Sandbox Code Playgroud)
这会在JS引擎中运行代码的时间足以产生请求.然后它在等待时空转.其他JS可以在这一点上运行,UI完全流畅和互动,一切都很棒.然后突然间,所有这10个请求立即解决.然后我们的回调像魔术一样被调用10次.
这是有效的,因为我们每次调用时都会clicked()创建一个新的函数对象,并将其传递给doAjax()函数.因此,有10个唯一的回调函数对象在内存中挂出,每个函数对象都被函数绑定到一个特定的请求doAjax().当请求返回时,它会找到关联的回调对象并调用它.
这里的巨大优势在于,尽管javascript是单线程的,但你永远不会将该线程与等待相关联.如果你的JS线程很忙,那应该只是因为它正在积极地运行代码.因此,即使JS是单线程的,您的代码隐式保存任意数量的任何异步任务的状态也是微不足道的.
回调的同步方法通常用于不同的目的.喜欢听众或代表.就像告诉对象A在数据发生变化时回调一样.虽然不是严格的异步,但通常不会立即调用该回调.相反,它将在稍后响应事件的某种用户操作而被调用.
由于正在执行的 JavaScript 是异步的,因此如果您在发出异步请求后放置任何旧函数,则它可能会在原始请求完成之前被调用。原始请求将在开始(发出)后立即返回,而不是完成。
如果您需要对异步请求的结果执行某些操作,或者将请求链接在一起等,您将需要一个回调以确保在上一步完成之前不会开始下一步。