js 事件驱动机制
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 事件驱动机制的更多相关文章
- JS事件驱动机制
还记得当初学JAVA-GUI编程时学习过事件监听机制,此时再学习JavaScript中的事件驱动机制,不免简单.当初学习时也是画过原理图,所以从原理图开始吧! js是采用事件驱动(event-driv ...
- Node.JS事件驱动机制
1.事件驱动程序绑定事件及事件的处理程序 eventEmitter.on('eventName', eventHandler); 我们可以通过程序触发事件 // 触发事件 eventEmitter.e ...
- js 事件驱动原理
还记得当初学JAVA-GUI编程时学习过事件监听机制,此时再学习JavaScript中的事件驱动机制,不免简单.当初学习时也是画过原理图,所以从原理图开始吧! js是采用事件驱动(event-driv ...
- node.js零基础详细教程(4):node.js事件机制、node异步IO操作
第四章 建议学习时间3小时 课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...
- 如何通过setTimeout理解JS运行机制详解
setTimeout()函数:用来指定某个函数或某段代码在多少毫秒之后执行.它返回一个整数,表示定时器timer的编号,可以用来取消该定时器. 例子 ? 1 2 3 4 5 console.log(1 ...
- Nginx——事件驱动机制(雷霆追风问题,负载均衡)
事件处理框架 所有的worker进程都在ngx_worker_process_cycle方法中循环处理事件,处理分发事件则在ngx_worker_process_cycle方法中调用ngx_proce ...
- 从浏览器多进程到JS单线程,JS运行机制的一次系统梳理
前言 见解有限,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正. ----------超长文+多图预警,需要花费不少时间.---------- 如果看完本文后,还对进程线程傻傻分不清,不清楚浏 ...
- JS学习笔记:(三)JS执行机制
首先我们先明确一点:JavaScript是一门单线程语言.单线程也就是说同一时间只能执行一个任务,所有的任务都必须排队顺序执行.那么如果一个任务耗时很长,阻塞了其它任务的执行,就会给用户造成不友好的体 ...
- js 运行机制
<script> console.log(1) setTimeout(function(){ console.log(3) },0) console.log(2) </script& ...
随机推荐
- 1.Netty 实战前言
1.参考文档:Netty实战精髓篇 2.Netty介绍: Netty是基于Java NIO的网络应用框架. Netty是一个NIO client-server(客户端服务器)框架,使用Nett ...
- 使用remix的solidity在线编译环境部署一个faucet合约
一.浏览器打开https://remix.ethereum.org 地址 点击"+"新建一个sol文件,命名为faucet.sol 然后在代码区输入solidity代码 选择相关插 ...
- 2019.8.30 记录一个Swiper的使用
导入 flutter_swiper: ^1.1.6 引入 import 'package:flutter_screenutil/flutter_screenutil.dart'; 已下 ...
- JQuery 中each的使用方法
JQuery中的each函数在1.3.2的官方文档中的描述如下: each(callback) 以每一个匹配的元素作为上下文来执行一个函数. 意味着,每次执行传递进来的函数时,函数中的this关键字都 ...
- c++关于字符串的读入和截取
#include<iostream>#include<string>#include<vector>using namespace std;vector<st ...
- ingress部署
# 手动部署 # 部署ingress-nginx 官方地址:https://github.com/kubernetes/ingress-nginx # 参考链接:https://www.jianshu ...
- cefsharp文档
原文链接:https://github.com/cefsharp/CefSharp/wiki/CefSharp中文帮助文档#a1_1 CefSharp中文帮助文档 目录 基础知识 1.1 cefsha ...
- JavaScript基础之变量的自增与自减
一.自增(++) ⑴什么是自增? 通过自增运算符可以使变量在自身的基础上加一: 对于一个变量自增以后,原变量的值会立即自增一: 示例: <!DOCTYPE html> <html l ...
- XML -- XML基础知识
1.XML的结构 XML的结构采用的是树结构,树结构就是一种一对多的关系结构. XML必定有一个根节点.因为,在解析这个XML时,需要有个起始位置进行遍历解析,这个跟节点就是起始位置. 2.XML的元 ...
- 回文数二(acm训练)
问题 1161: [回文数(二)] 时间限制: 1Sec 内存限制: 128MB 提交: 133 解决: 51 题目描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. ...