JavaScript Concurrency model and Event Loop 并发模型和事件循环机制
原文地址:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
JavaScript 有一个基于 event loop 的并发模型,这个模型和其他如 Java 和 C 语言的模型是不同的。
Runtime concepts 运行时概念
下面是一个可视化的模型展示,现代 JavaScript 引擎实现并着重优化了这个模型。
Stack 栈
函数从一个调用栈中执行,这个栈由多个调用栈帧组成
- function foo(b) {
- var a = ;
- return a + b + ;
- }
- function bar(x) {
- var y = ;
- return foo(x * y);
- }
- console.log(bar()); //returns 42
调用 bar 时,第一个调用帧被创建,这个帧包含 bar 的参数和局部变量,在 bar 内部调用 foo,第二个调用帧被创建,然后入栈,放在第一个调用帧的上面。
当 foo 执行完成以后,栈顶的帧就会出栈。当 bar 也执行完成之后,栈为空。
Heap 堆
对象被分配到一个堆中,堆这个名字就象征着一大块没有结构的内存区域。
Queue 队列
一个 JavaScript 运行时有一个消息队列(message queue),这是一个待处理消息列表,每个消息有相应的函数会被调用来处理这个消息。
在 event loop 的某个时刻,运行时开始处理队列中的消息,从最早的那一个开始。这个消息将被移出队列,对应的函数会被调用,并将这个消息作为参数。
同样和前面一样,这个函数调用也会给这个函数产生一个调用栈帧。
函数执行的过程会一直持续到调用栈再次为空,然后 event loop 会继续处理消息队列中的下一个消息 (如果有的话)
Event loop 事件循环
事件循环的实现原理类似于下面的伪代码:
- while (queue.waitForMessage()) {
- queue.processNextMessage();
- }
如果当前没有事件消息,queue.waitForMessage() 会同步地等待
Run-to-completion 执行到完成
在其它消息被处理之前,当前的消息会完全处理结束。这在你分析自己的代码时有非常好的特性,比如当一个函数执行时,它不会被提前阻止,在其它代码运行之前会完整地执行(这些代码可能会改变此函数操作的数据)。这个 C 语言不同,例如,当一个线程中的一个函数运行,它可能会被中止,因为运行时要去处理其它线程中的另外一些代码。
这个模型的一个缺点就是,如果一个消息需要过长的处理时间,web 应用将无法处理其它如点击或者鼠标滚动事件。浏览器会弹出对话框“程序需要过长事件无法运行”的对话框来处理这种消息。一个好的实践是将消息处理时长减少,如果可以,将一个消息分成多个消息。
Adding message 添加消息
在 web 浏览器中,只要一个事件发生并且有一个事件监听绑定到这个事件,就会添加消息到队列中。如果没有监听到,事件就丢失了。
函数 setTimeout 有两个参数,一个将添加到队列中的消息,一个代表延迟的时间值(毫秒,默认为0)。这个时间代表添加到队列前的最少等待时间。
如果队列中没有其它消息,则这个消息将在延迟之后立即被处理。然而,如果有其它消息,setTimeout 的消息还要等待其它消息处理。所以第二个参数仅仅代表最少时间,并不保证确切的时间长度。
下面是一个例子
- const s = new Date().getSeconds();
- setTimeout(function() {
- // prints out "2", meaning that the callback is not called immediately after 500 milliseconds.
- console.log("Ran after " + (new Date().getSeconds() - s) + " seconds");
- }, 500);
- while(true) {
- if(new Date().getSeconds() - s >= 2) {
- console.log("Good, looped for 2 seconds");
- break;
- }
- }
Zero delays 零延时
延时设置为 0 并不表示回调函数会立即执行,是否执行取决于队列中等待的任务的数量。
在下面的例子中,cb1 是最后执行的,因为它要等待队列前面的任务执行完毕。
- (function() {
- console.log('this is the start');
- setTimeout(function cb() {
- console.log('this is a msg from call back');
- });
- console.log('this is just a message');
- setTimeout(function cb1() {
- console.log('this is a msg from call back1');
- }, 0);
- console.log('this is the end');
- })();
- // "this is the start"
- // "this is just a message"
- // "this is the end"
- // note that function return, which is undefined, happens here
- // "this is a msg from call back"
- // "this is a msg from call back1"
几个运行时之间通信
一个 web worker 或者 一个跨域的 iframe 都要自己的栈、堆和消息队列。
两个不同的运行时只能通过 postMessage 方法进行通信。
另外一个运行时如果监听 message 时间,就可以添加消息到自己的队列。
Never blocking 非阻塞
时间循环机制的一个非常有趣的特性的就是永远不会阻塞。
处理 I/O 事件通常都通过事件和回调函数执行。当应用在等待一个数据库查询或者 XHR 请求的结果时,可以同时处理其它事情比如用户输入。
遗留问题也是存在的,比如 alert 或者 同步的XHR,不过好的实践是避免使用它们。
JavaScript Concurrency model and Event Loop 并发模型和事件循环机制的更多相关文章
- Javascript并发模型和事件循环
Javascript并发模型和事件循环 JavaScript的"并发模型"是基于事件循环的,这个并发模型有别于Java的多线程, javascript的并发是单线程的. Javas ...
- 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)
JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...
- JavaScript 运行机制:Event事件循环机制
JavaScript Event事件循环机制 JS是单线程的,浏览器只分配一个主线程给JS.一次只能执行一个任务,当前任务执行完后在可以执行下一个任务.任务多时,就会形成任务队列排队等待执行.但是非常 ...
- javascript事件循环机制 浅尝手记
引入 众所周知Javascript是一个单线程的机制,虽然可以依托多线程的浏览器实现页面如何实现页面复杂的渲染.事件响应,但仍不会改变其单线程的本质:所以对于js的事件循环机制的了解是一个前端人员的必 ...
- 深入理解JavaScript事件循环机制
前言 众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心.可看HTML规范中的这段话: To ...
- 对javascript EventLoop事件循环机制不一样的理解
前置知识点: 浏览器原理,浏览器内核5种线程及协作,JS引擎单线程设计推荐阅读: 从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理 [FE]浏览器渲染引擎「内核」 js异步编程,Promise ...
- 【运行机制】 JavaScript的事件循环机制总结 eventLoop
0.从个例子开始 //code-01 console.log(1) setTimeout(() => { console.log(2); }); console.log(3); 稍微有点前端经验 ...
- JavaScript中的事件循环机制跟函数柯里化
一.事件循环机制的理解 test();//按秒输出5个5 function test() { for (var i = 0; i < 5; i++) { setTimeout(() => ...
- JS JavaScript事件循环机制
区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...
随机推荐
- 第六节:WebApi的部署方式(自托管)
一. 简单说明 开篇就介绍过WebApi和MVC相比,其中优势之一就是WebApi可以不依赖于IIS部署,可以自托管,当然这里指的是 .Net FrameWork 下的 WebApi 和 MVC 相比 ...
- [Android] Android 类似今日头条顶部的TabLayout 滑动标签栏 效果
APP市场中大多数新闻App都有导航菜单,导航菜单是一组标签的集合,在新闻客户端中,每个标签标示一个新闻类别,对应下面ViewPager控件的一个分页面,今日头条, 网易新闻等. 本文主要讲的是用:T ...
- [物理学与PDEs]第1章第9节 Darwin 模型 9.2 Maxwell 方程组的一个定解问题
设 $\Omega$ 为一有界区域, 外部为理想导体 $(\sigma=+\infty)$, 则 $\Omega$ 中电磁场满足 Maxwell 方程组 $$\beex \bea \ve\cfrac{ ...
- Educational Codeforces Round 52 (Rated for Div. 2)
题目链接 A. Vasya and Chocolate 题意 已知钱,价格,赠送规则求最多获得巧克力数 思路常规算即可 代码 #include <bits/stdc++.h> #defin ...
- Coursera, Big Data 3, Integration and Processing (week 5)
Week 5, Big Data Analytics using Spark Programing in Spark Spark Core: Programming in Spark us ...
- js打印WEB页面内容代码大全
第一种方法:指定不打印区域 使用CSS,定义一个.noprint的class,将不打印的内容放入这个class内. 详细如下: <style media=print type="tex ...
- 【洛谷P2660烤鸡】
题目背景 猪猪hanke得到了一只鸡 题目描述 猪猪Hanke特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke吃鸡很特别,为什么特别呢?因为他有10种配料(芥末.孜然等),每种配料可以放1—3克, ...
- Bmob后端云学习(未完)
Bmob后端云学习 BaaS(后端即服务:Backend as a Service)公司为移动应用开发者提供整合云后端的边界服务. 这种服务的一个代表就是Bmob后端云,BAT和亚马逊 ,都有这类产品 ...
- Alpha 事后诸葛亮(团队)
前言 事后诸葛亮?作业名真的不好听,下一届还要沿用吗? 队名:小白吃 通向hjj博客的任意门 思考总结 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? ...
- Java_运算符
目录 一.算术运算符 二.关系运算符 三.位运算符 四.赋值运算符 五.条件运算符 六.instanceof 运算符 七.逻辑运算符 一.算术运算符 加 减 乘 除 取余 自增 自减(+ - * / ...