js的回调及event-loop

参考文章:阮一峰

一、javascript是单线程

作为浏览器脚本语言,与使用用途有关决定了只能是单线程。

二、任务队列

单线程意味着,所有任务需要排队,前一个任务结束,才会执行后一份任务,如果前一个任务耗时很长,后一个任务就不得不一致等待。
如果排队是因为计算量大,可以理解,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢,比如(比如AJAX操作从网络读取数据),不得不等着结果出来,再往下执行。
JavaScript设计者意识到,主线程可以不管IO设备,挂起处于等待中的任务,先执行排在后面的任务,等到IO设备返回了结果,在继续执行挂起的任务。
于是,任务可以分成两种,一种是同步任务,另一种是异步任务。同步任务指在主线程排队执行的任务,只有前一个任务执行完毕,才能去执行后面的任务;异步任务指。不进主线程,而是进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进给主线程执行。

  • 所有任务都在主线程上执行,形成一个任务执行栈。
  • 主线程外,还存在一个“任务队列”,只要一步任务有了运行结果,就在“任务队列”之中放置一个事件。
  • 一旦“执行栈”中所有同步任务执行完毕,系统就会读取“任务队列”,看里面有哪些事件,那些异步任务,结束等待状态,进入执行栈,开始执行。
  • 主线程不断重复上面的第三步骤。
  • 当主线程阻塞时,任务队列仍然是能够被推入任务的,这也是为什么当前页面进程阻塞时触发的点击事件会发进程恢复后一次执行。

只要主线程空了,就会去读取“任务队列”,这是Javescropt的运行机制,这个过程会不断的重复。

三、事件和回调函数

只要指定过回调函数,这些事件发生时就会进入“任务队列”,等待主线程读取。
所谓回调函数,就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
“任务队列”是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本是自动的,只要执行栈一清空,“任务队列”上第一位的事件就会自动进入主线程,但是,由于存在“定时器”功能,主线程首先要检查执行时间,某些事件只有到了规定的时间,才能返回主线程。

四、Event Loop

主线程从“任务队列”中读取事件,这个过程是循环不断的,所以着呢个运行机制称为Event Loop(事件循环)。
执行栈中的代码(同步任务),总是在读取“任务队列”(异步任务)之前执行。

五、定时器

setTimeout()接受两个参数,第一个是回调函数,第二个是推迟的毫秒数。
注意:
setTimeOut()只是将事件插入了“任务队列”,必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。如果当前代码耗时很长,有可能要等很久,所以并没有办法保证,毁掉函数一定会在setTimeout()指定的事件执行。

你可能感兴趣的:(js的回调及event-loop)