JavaScript单线程
首先记住一句话 —— JS 是单线程
的语言,所谓“单线程”就是一根筋,对于拿到的程序,一行一行的执行;也就是说,同一个时间只能做一件事;
JavaScript为什么不能有多个线程呢?
作为浏览器脚本语言,JavaScript的主要用途是与用户互动
,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
所以,为了避免复杂性,从一诞生,JavaScript就是单线程
,这已经成了这门语言的核心特征,将来也不会改变。
任务队列
- 同步任务(synchronous)
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务; - 异步任务(asynchronous)
异步任务指的是,不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。简言之就是JS只有一个主线程,主线程执行完执行栈的任务后去检查异步的任务队列,如果异步事件触发,则将其加到主线程的执行栈。
setTimeout
举例
console.log('1')
setTimeout(console.log, 1000, '2')
console.log('3')
//输出 1 3 2
以上一共三行代码,该程序被执行的时候,会依次挨行执行
第一步,执行主线程
第一行,将结果 1
打印出来
第二步,执行第二行,注意此时会将这个操作暂存到其他地方,因为setTimeout
是一个异步执行操作。
第三步,执行主线程
第三行,将结果 3
打印出出来
第四步,等待最后一行程序(一共三行)都全部执行完了,然后立马实时查看刚才暂存的异步操作(任务队列
)。如果有可执行的,就立即继续执行。
第五步,执行完毕之后,主线程
不断重复上面的第四步
Event Loop。
只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。
Event Loop
- 提到异步,就必须提
event-loop
主线程从任务队列
中读取事件,这个过程是循环不断
的,所以整个的这种运行机制又称为Event Loop
,中文翻译叫做“事件轮询”
常用的异步操作
- 网络请求,如ajax http.get
- IO 操作,如readFile readdir
- 定时函数,如setTimeout setInterval
回调函数
var ajax = $.ajax({
url: 'data.json',
success: function () {
console.log('success')
}
})
上面代码中$.ajax()需要传入两个参数进去, url
和success
,其中url是请求的路由,success是一个函数。这个函数传递过去不会立即执行,而是等着请求成功之后才能执行。对于这种传递过去不执行,等出来结果之后再执行的函数,叫做callback
,即回调函数
所谓回调函数
,就是那些会被主线程挂起来的代码。异步必须指定回调函数,当主线程开始执行异步,就是执行对应的回调函数。