1、浏览器端的事件驱动机制

javascript 在浏览器端运行是单线程的,这是由浏览器决定的,这是为了避免多线程执行不同任务会发生冲突的情况。也就是说我们写的javascript 代码只在一个线程上运行,称之为主线程(HTML5提供了web worker API可以让浏览器开一个线程运行比较复杂耗时的 javascript任务,但是这个线程仍受主线程的控制)。

有些操作比如说获取远程数据、I/O操作等,他们都很耗时,如果采用同步的方式,那么进程在执行这些操作时就会因为耗时而等待,就像上面那样,下面的任务也只能等待,这样效率并不高。

为了解决单线程带来的阻塞问题很多操作系统实现了异步编程机制,浏览器中也是这么做的,主要表现如下:

(1)只在主线程中运行 javascript 代码

(2)主线程一启动就进入事件循环,整个过程就是不断的循环,不断地执行回调函数

(3)遇到网络请求、I/O操作等时,浏览器会单开工作线程来处理,并设置相应的观察者,然后立即返回主线程,主线程继续执行下面的任务

(4)浏览器开的线程处理好任务或者有监听的事件后会用得到的数据(或输入)形成一个事件,放在相应观察者的事件队列中,事件队列是在主线程中

(5)主线程不断的循环,不断检查事件队列,通过遍历事件依次执行事件对应的回调函数

假设你发起了一个AJAX请求,无论你把这个请求写在什么地方,它始终都在回调函数里。 因为事件驱动机制就是把一切抽象为事件,代码开始执行也是一个事件,也会隐式调用回调函数,调用回调函数就是开始执行代码。然后主线程发起异步任务后就会随即返回,继续执行"代码开始事件"对应回调函数里的代码,等到这个回调函数执行完毕,就会执行下一个事件。在这之间,Ajax线程会完成请求,然后把请求完成的事件(包含返回的数据)发送到事件队尾中等待处理,等到主线程执行到这个事件时,指定的回调函数即被执行。

watcher机制 watcher,观察者,是事件驱动系统重要的机制。

setTimeout称为定时器,这是浏览器给的API。 每当你使用定时器,这个函数将会设置一个watcher,观察者。主线程会不断的循环,不断的"经过"这里检查时间,当主线程检查时间间隔符合要求时,就会产生一个定时器事件,加入到这个watcher事件队列中并执行回调函数。

因此执行setTimeout只是在时间到的时候产生了要调用回调函数的消息加入到了事件队列中,因此,回调函数并不一定在指定的时间时调用,它取决于前面有多少等待处理的事件。

除此之外,还有I/O观察者、网络请求观察者、鼠标事件观察者、键盘事件观察者等等等等,我们经常遇到事件监听函数会让你绑定一个回调函数,这种监听函数一般就会设置watcher,其他线程产生的事件也会放到相应watcher的事件队列中,因此每个watcher会产生自己的事件队列。主线程在循环的时候,实际上是在依次调用这些watcher,检查每个watcher的事件队列,有事件就执行相应的回调。

它的过程就是 :进程一启动就进入事件循环;有监听就添加watcher;遍历watcher下的事件队列。

执行下一个watcher 事件驱动机制,它会有各种各样的事件,大量的事件,它所做的一切都跟处理事件有关。但并不是所有的事件都有watcher,如果都有,主进程任务会变得非常繁重,况且有些事件我们并不关心,例如你只写了一个定时器,代表你关心这个事件,那么点击事件、网络请求事件就不用关心,因为你根本就没写啊,也就没有watcher。

2、在 node.js上的事件驱动机制

javascript 在 node.js上的事件驱动机制与浏览器端大致相同,都是单线程,都有event loop,上面讲的javascript在浏览器端的事件循环机制在node上也是大致一样的,不同的是执行者和执行者的行为不一样,因为他们关注的任务不一样:

node端异步机制和事件循环更加纯粹一些。node为了支持高并发,所有的API几乎都是异步的,这样会充分利用操作系统的其他线程来帮忙完成任务,主线程只负责事件消费。例如当web server接收到请求,node就把它关闭,交给其他线程进行处理,然后去服务下一个web请求。当这个请求完成,它被放到处理队列,当到达队列开头,这个结果被返回给用户。这样的话webserver一直接受请求而不等待任何读写操作,这种非阻塞型I/O性能很强。

浏览器端是浏览器负责执行BOM API,管理线程,处理用户输入信息等,在node上是node的一个核心库libuv负责执行node API,管理主线程(运行javascript)和工作线程等。

解释下“事件驱动”这个概念。所谓事件驱动,是指在持续事务管理过程中,进行决策的一种策略,即跟随当前时间点上出现的事件,调动可用资源,执行相关任务,使不断出现的问题得以解决,防止事务堆积。

Nodejs设计思想中以事件驱动为核心,事件驱动在于异步回调,他提供的大多数api都是基于事件的、异步的风格。而事件驱动的优势在于充分利用系统资源,执行代码无须阻塞等待某种操作完成,有限的资源用于其他任务。事件驱动机制是通过内部单线程高效率地维  护事件循环队列来实现的,没有多线程的资源占用和上下文的切换。

出处:https://www.jianshu.com/p/3115def9e1fe

js 事件驱动机制的更多相关文章

  1. JS事件驱动机制

    还记得当初学JAVA-GUI编程时学习过事件监听机制,此时再学习JavaScript中的事件驱动机制,不免简单.当初学习时也是画过原理图,所以从原理图开始吧! js是采用事件驱动(event-driv ...

  2. Node.JS事件驱动机制

    1.事件驱动程序绑定事件及事件的处理程序 eventEmitter.on('eventName', eventHandler); 我们可以通过程序触发事件 // 触发事件 eventEmitter.e ...

  3. js 事件驱动原理

    还记得当初学JAVA-GUI编程时学习过事件监听机制,此时再学习JavaScript中的事件驱动机制,不免简单.当初学习时也是画过原理图,所以从原理图开始吧! js是采用事件驱动(event-driv ...

  4. node.js零基础详细教程(4):node.js事件机制、node异步IO操作

    第四章 建议学习时间3小时  课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...

  5. 如何通过setTimeout理解JS运行机制详解

    setTimeout()函数:用来指定某个函数或某段代码在多少毫秒之后执行.它返回一个整数,表示定时器timer的编号,可以用来取消该定时器. 例子 ? 1 2 3 4 5 console.log(1 ...

  6. Nginx——事件驱动机制(雷霆追风问题,负载均衡)

    事件处理框架 所有的worker进程都在ngx_worker_process_cycle方法中循环处理事件,处理分发事件则在ngx_worker_process_cycle方法中调用ngx_proce ...

  7. 从浏览器多进程到JS单线程,JS运行机制的一次系统梳理

    前言 见解有限,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正. ----------超长文+多图预警,需要花费不少时间.---------- 如果看完本文后,还对进程线程傻傻分不清,不清楚浏 ...

  8. JS学习笔记:(三)JS执行机制

    首先我们先明确一点:JavaScript是一门单线程语言.单线程也就是说同一时间只能执行一个任务,所有的任务都必须排队顺序执行.那么如果一个任务耗时很长,阻塞了其它任务的执行,就会给用户造成不友好的体 ...

  9. js 运行机制

    <script> console.log(1) setTimeout(function(){ console.log(3) },0) console.log(2) </script& ...

随机推荐

  1. 使用 jenkins 为 nginx 增加上下文

    每次需要在Nginx增加上下文,都需要添加如下两段 ​ server.conf upstream serverdownloadPage { server 10.11.19.6:3023; } ​ ht ...

  2. 版本控制工具 svn 二

    一.图标 忽略图标 实例 二.版本 回滚 tortoisesvn ——> 版本更新——>一般情况下使用 “显示日子” 回滚 三.版本冲突 版本冲突产生原因 多人先后提交文件,每个人提交的文 ...

  3. 第11章 Spring Boot使用Actuator

    在生产环境中,需要实时或定期监控服务的可用性,spring-Boot的Actuator 功能提供了很多监控所需的接口. Actuator是Spring Boot提供的对应用系统的自省和监控的集成功能, ...

  4. Linux之yum软件管理

    YUM yum = Yellow dog Updater, Modified主要功能是更方便的添加/删除/更新RPM包.它能自动解决包的倚赖性问题. 它能便于管理大量系统的更新问题 yum特点 *可以 ...

  5. 【u-boot】u-boot中initf_dm()函数执行流程(转)

    前部分设备模型初始化 为了便于阅读,删掉部分代码,只留关键的过程: static int initf_dm(void){    int ret;    ret = dm_init_and_scan(t ...

  6. .NET Core 3时代!如何使用DevExpress WPF创建应用

    DevExpress广泛应用于ECM企业内容管理. 成本管控.进程监督.生产调度,在企业/政务信息化管理中占据一席重要之地.通过DevExpress WPF Controls,您能创建有着强大互动功能 ...

  7. [Functional Programming] Add, Mult, Pow, isZero

    const log = console.log; // zero :: &fa.a const zero = f => x => x; // zero is F // once : ...

  8. freemarker页面静态化

    1.工程结构 2. Student public class Student { private int id; private String name; private String address ...

  9. jquery keyup()方法 语法

    jquery keyup()方法 语法 作用:完整的 key press 过程分为两个部分,按键被按下,然后按键被松开并复位.当按钮被松开时,发生 keyup 事件.它发生在当前获得焦点的元素上.ke ...

  10. 顺序表应用4-2:元素位置互换之逆置算法(数据改进)(SDUT 3663)

    Problem Description 一个长度为len(1<=len<=1000000)的顺序表,数据元素的类型为整型,将该表分成两半,前一半有m个元素,后一半有len-m个元素(1&l ...