javascript的并发模型

2017-08-11

javascript运行在单线程里,意思就是js每次只能执行一段代码。js有自己的并发模型,由栈、堆和队列组成。如下图

JavaScript 引擎从顶部开始执行脚本,然后向下工作,创建执行上下文并将函数推入和弹出调用堆栈

如果函数需要很长时间才能执行,那么在函数执行期间,用户将无法在 Web 浏览器上执行任何操作,页面卡死

举个例子🌰

function task(message) {
  // 模拟耗时任务
  let n = 10000000000;
  while (n > 0){
    n--;
  }
  console.log(message);
}

console.log('开始执行');
task('耗时任务');
console.log('结束!');

上面的代码执行,每次执行一个函数入栈,在执行 task 函数的时候,由于是一个耗时函数,会阻塞后面代码的执行,直到 task 函数执行完成后,出栈后继续执行最后的 console.log('结束!')

函数调用形成了一个栈帧

给对象分配内存都在堆里实现的

队列

在js执行的过程中,所有的回调函数都会放到消息队列,当栈为空的时候,就从消息队列中取出函数逐一处理,直到栈为空时消息处理结束,例如 setTimeout 等函数

事件循环

不同于c++等多线程语言,js是单线程,所以需要事件循环来检测栈是否为空,然后把函数或者消息进栈执行,类似于这样实现

while (queue.waitForMessage()) {
    queue.processNextMessage();
}

浏览器的并发机制

浏览器提供了Web APIs,事件循环和回调队列,如下图


web APIs:包含ajax,setTimeout,Events等等

回调队列:所有的事件监听都会放到回调队列中去,例如点击,focus事件都放到此队列等待响应

事件循环:监听栈是否为空,然后把回调函数放到栈中执行

console.log(1);
setTimeout(function() {
  console.log(2)
}, 0);
console.log(3);

上面代码执行到setTimeout的时候回放到回调队列里面去,然后其他函数从上到下执行完毕,栈为空的时候就把回调函数放到栈中执行,所以结果输出为 1,3,2

回调队列的分类

执行回调队列的过程,浏览器会有两个任务队列,优先执行微任务队列的回调,再执行宏任务队列的回调。

宏任务

script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)

微任务

Promise.then
Object.observe
MutaionObserver
process.nextTick(Node.js 环境)

参考资料

本文为原创,未经授权,禁止任何媒体或个人自媒体转载
商业侵权必究,如需授权请联系340443366@qq.com
标签: javascript

评论

Loading...

最新评论

相关推荐

ts之类型谓词
在了解类型谓词之前,我们先来了解联合类型。 联合类型 日常开发中,我们会定义为一个支持多种类型的变量,比如一个变量可...
vscode自定义组件属性自动提示
在封装业务组件的时候,组件如果可以提供良好的属性提示,对开发的同事是一种很好的体验。 下面有两种方案可以实现属性文档提...
h5のvideo踩坑
video是h5新增的标签,可以通过 video 标签播放 ogg、mp4 、webm 等格式的视频。 🌽...
scroll-top-icon