线程与进程

线程与进程

  • 进程是指一个内存中运行的应用程序,保存了上下文;

  • 线程是进程中的一个执行流程。

rAF与rIC

参考: requestIdleCallback和requestAnimationFrame详解

浏览器每帧的任务

  • 处理用户的交互

  • JS 解析执行

  • 帧开始。处理窗口尺寸变更、页面滚动

  • requestAnimationFrame(rAF)

  • 布局

  • 绘制

requestIdleCallback

浏览器空闲时执行,属于低优先级任务。不建议在里面操作DOM或者Promise操作

var taskId = requestIdleCallack(function (idle) {
    idle.didTimeout // 任务是否超时,boolean
    idle.timeRemaining() // 当前帧剩余时间
}, {
    timeout: 0, // 如果超过这个事件,强制执行
})
cancelIdleCallback(taskId) // 取消任务

requestAnimationFrame

执行时间间隔为屏幕刷新一次所需的时间。

可以用来判断当前是否是活动页面,如果不是,requestAnimationFrame()的回调不会执行 setTimeout回调函数的执行时间不固定,这是由Event Loop决定的,所以会导致卡顿

var taskId = requestAnimationFrame(function () {})
cancelAnimationFrame(taskId)

web worker

Web Worker 创建多线程环境,worker 线程在后台执行不影响主线程。好处是,处理计算密集型或高延迟的任务不会阻塞主线程。

  • 同源限制

  • DOM限制。无法读取主线程所在网页的DOM、window、document等对象,但可以读取主线程 navigator、location对象

  • 脚本限制。不能执行 alert、 confirm等方法,可使用 XMLHttpRequest

  • 文件限制。不能打开本机文件系统

// 主线程
var worker = new Worker('work.js')
worker.postMessage({}) // 发送
worker.onmessage = function (e) {
    console.log(e.data) // 接受
}
worker.onerror(function (e) {}) // 监听错误
worker.terminate() // 关闭子线程

// 子线程
this.addEventListener('message', function (e) { // 接受
    this.postMessage('call') // 发送
})
this.close() // 子线程关闭自己

Event-Loop(事件循环)

单线程运行不阻塞的机制,即异步原理。

进程与线程

https://www.cnblogs.com/jokezl/p/10469503.html

进程是指一个内存中运行的应用程序,保存了上下文;线程是进程中的一个执行流程。JS是单线程,可节省内存、节约上下文切换时间、且没有锁的问题。

浏览器中的 Event Loop

当执行异步代码时,会被挂起加入到Task队列中,一旦执行栈为空,Event Loop就会从Task队列中拿到所需要执行的代码放入执行栈中执行,所以本质上JS中的异步还是同步行为。

不同的任务源会被分配到不同的Task队列中,任务源分为微任务(jobs)宏任务(task)

  • 微任务:promiseObject.observe

  • 宏任务:script、setTimeoutsetIntervalrequestAnimationFarme、UI rendering。

  • 首先执行全局script同步代码,这些同步代码有一些是同步语句,有一些是异步语句(如setTimeout)

  • 全局script代码执行完毕后,执行栈会被清空

  • 从微任务队列中取出队首的回调任务,放入执行栈中执行,执行完后微任务长度减1,直到长度为0。如果执行微任务过程中又产生了新的微任务,那么加入到微任务队列末尾继续等待被执行完毕

  • 所有微任务执行完毕后,取出队首的宏任务,放入执行栈中执行,直到宏任务执行完毕。

  • 重复3-4

Nodejs 中的 Event Loop

nodejs 的 Event Loop中,宏任务队列的回调任务有6个阶段

  1. timers执行setTimeoutsetinterval预定的callback

  2. I/O callbacksfs等

  3. idle, preparenode内部调用

  4. poll 获取新的I/O事件,node可能会阻塞

  5. check 执行setImmediate()callbacks

  6. close callbacks 执行 xx.on('close', ...) 这些 callbacks

  7. 宏任务:主要有timesI/O callbackssetImmediateclose callbacks 4个

  8. 微任务:process.nextTickpromiseObject.observe

  9. 执行全局script的同步代码

  10. 执行微任务,先执行process.nextTick中的所有任务,再执行其他微任务

  11. 执行宏任务,每当一个阶段执行完后,有微任务产生则执行微任务,若无则继续执行一下个阶段的宏任务

Last updated

Was this helpful?