回调回调(Callback)是指将一部分代码逻辑以某种形式,通常是函数,交付给另一方,而另一方会在某种情况下执行交付的代码。如果交付是以函数形式进行的,那么这些函数也被称为回调函数,当然,回调并非只能采用回调函数,语言可以拓展出任意一种设计,比如委托。
为何需要回调?使用回调的原因在于,虽然知道需要执行的逻辑,但无法确定执行的具体时间,这往往是异步执行造成的。比如,我们知道需要在数据上传完成后通知用户,但无法确定上传完成的具体时间,因为上传采用了异步的方式。
什么是异步和同步?异步不会保留控制权,当你调用支持异步的函数时,并不会产生阻塞,这意味着可以立即进入下一行代码,不必等待函数的执行结果,异步通常是由多线程来实现的。与异步相反的是同步,同步函数会保留控制权,这意味着必须等待函数执行完毕,才能进入下一行代码。
需要说明的是,这里提到的函数并不是回调函数,而是对应了另一方,回调函数往往会作为这些函数的实参。
什么是线程和进程?线程被包含在进程内,你可以将其理解为实际执行的代码,一个进程可以拥有多个线程。线程通过串行的方式执行其包含的代码,一行代码执行完毕后,才会进入另一行。而多个线程可以被并行执行,不需要彼此等待,并共享进程内的资源。虽然在逻辑上具有并行的效果,但线程仍可能以并发的方式获取 CPU 的使用权,因为不存在无限的资源来实现真正的同时执行。
通过多线程,你可以实现异步操作,以避免不必要的等待时间。比如,我们可以创建一个新的线程来执行耗时的网络存储任务,以便用户在此期间进行其他操作。
进程可以被理解为操作系统中执行的程序或应用,比如,打开的记事本应用。
在下面的 JavaScript 代码中,message会作为回调函数传递给setTimeout,并在3秒后显示消息。
callbacks_and_delegates.js// 回调函数 message,显示一条消息
function message() {
console.log('一条消息?!')
}
// 函数 setTimeout 将在 3 秒后调用 message
setTimeout(message, 3000)
// console.log 会紧接着 setTimeout 执行
console.log('请等待 3 秒钟!')请等待 3 秒钟!约 3 秒后…一条消息?!JavaScript 的 setTimeout 是否为异步函数?是的,无论 JavaScript 的运行环境是否支持多线程,setTimeout都是一个异步函数。一些观点以线程数量为依据持相反的观点,但异步和多线程并没有必然的联系,多线程只是实现异步的方式之一。