我读到过回调使JavaScript异步。但我不确定我是否理解了这个解释。这是我得到的
回调函数允许我们异步地做事情,因为它们保证回调之前的行在加载之前已经完全完成下一行。
是真的吗?谢谢
首先,它不是启用任何东西的回调。node.js或甚至基于浏览器的javascript中的给定操作要么是异步的,要么不是异步的。它实际上与回调无关,尽管回调通常用于传递异步操作的结果。
例如,Javascript的array.forEach()
使用回调,但它不是异步的。异步操作是异步的,因为它们的底层实现是非阻塞的。通过调用函数来启动操作,操作在后台进行,其余代码继续运行。同时,当异步操作完成时,它通常需要告诉您的代码它已经完成,并可能传递一些结果。回调函数是用来通知异步操作完成的机制。
我读到回调使JavaScript异步。
不,那不是真的。回调也可以与同步操作一起使用。仅仅因为使用回调并不会使任何事情异步。操作的底层本机代码实现必须是异步的(例如Ajax调用或其他网络操作)。回调用于传递异步操作的结果。它们也有许多其他非异步用途。所以,回调只是异步操作中使用的一个工具,回调也是一个有许多其他用途的工具。你不能说callback === asynchronous
。
很难确切地说出你的意思,但我觉得这听起来不对。在使用异步操作时,代码通常不会按照文件中列出的顺序执行。例如,如果您这样做:回调函数允许我们异步地做事情,因为它们确保回调之前的代码行已经完全完成
console.log("async start");
callSomeAsyncOperation(function(result) {
console.log("async done");
});
console.log("I'm here now");
你会在日志中看到:
async start
I'm here now
async done
回调和事件队列解释
理解异步操作是如何工作的可能也很有用。Javascript在事件队列上工作。给定的Javascript代码序列运行到完成。完成后,引擎将查看事件队列中是否有更多的事件需要处理。如果是,则取出队列中的第一个事件,并调用为该事件注册的回调。这将启动一个新的Javascript代码序列。该代码将继续运行,直到完成。当它结束时,引擎检查另一个事件。如果有,则通过调用与该事件关联的回调来处理它。当没有更多事件要处理时,引擎进入休眠状态,等待下一个事件。当一个事件发生时(在主Javascript头之外),它会被添加到队列中,添加到队列的过程会导致JS引擎唤醒并为该事件提供服务。
在编写Javascript时,您经常会为事件注册和事件处理程序。这在Javascript中的工作方式是,你说你感兴趣的事件(这可能还包括指定一些其他信息,如你正在寻找事件的对象),然后你传递它是一个函数引用。实际上,您是在告诉Javascript引擎,希望它在此事件发生时调用您的函数引用。这种类型的函数引用被称为"回调"。它只是一个普通的函数,但是使用它的上下文被称为"回调",因为其他一些代码将在未来的某个时间通过执行你的函数"回调"。然后,您可以在函数引用中(在回调函数中)放置可以响应该事件的适当代码。根据事件的类型,您可能只被调用一次,也可能每次事件发生时都调用您。
您可以在这些参考文献中阅读有关此事件队列和回调如何工作的更多信息:
在等待节点回调时运行任意代码?
非阻塞HTTP服务器中的阻塞代码
Javascript/Node中的隐藏线程永远不会执行用户代码:这是可能的吗?如果是这样,它会导致一个神秘的竞争条件的可能性吗?JavaScript如何在后台处理AJAX响应?(写的是关于浏览器,但概念是一样的)
首先,让我们了解回调是什么(根据定义):
在计算机编程中,回调是一段可执行代码作为参数传递给其他代码,该代码预计会回调在方便的时候(执行)参数。调用可以是在同步回调中是立即的,或者可能在稍后发生时间为异步回调。在所有情况下,目的都是指定函数或子例程作为实体,这取决于语言,或多或少类似于变量。
现在,说到Javascript,回调并不总是异步的。例如:
function syncOperation(callback) {
callback();
}
syncOperation(function() {
console.log('a');
console.log('b');
});
console.log('c');
这个回调是同步的,因为它不做任何异步操作。如果您打开控制台并运行上面的代码,您将看到它将记录a
,然后是b
,然后是c
。
现在,让我们看一个异步的例子:
function asyncOperation(callback) {
setTimeout(callback, 0);
}
asyncOperation(function() {
console.log('a');
console.log('b');
});
console.log('c');
您将首先看到c
,然后是a
和b
。这是因为setTimeout
函数是异步运行的。
一些内置的Javascript函数是异步的,它们将运行,并且在某些时候,它们将调用作为参数传递回的函数。这就是为什么如果你这样做:
var a = 'text';
setTimeout(function() { a = 'new text'; }, 0);
console.log(a);
您将在控制台中看到text
,因为它将在变量更改之前运行。