原文地址在个人博客,转载请注明来源,谢谢!javascript
node是在前端领域常常看到的词。node对于前端的重要性已经不言而喻,掌握node也是做为合格的前端工程师一项基本功了。知道node、知道后端的一些东西,才能更好的与别人合做,发挥更大的价值。css
本文主要介绍了我对node的一些核心特性的理解,包括node架构、特色、机制、核心模块与简单应用。html
首先,node是一个平台,使用javascript做为编程语言,运行在服务端。服务端语言能作的,node通常都能作,并且有些状况下作的更好,由于它具备本身的特点。前端
node是javascript运行环境(runtime),就像浏览器同样,是一个平台。在浏览器中,V8引擎负责解释javascript,你在javascript调用的接口都是浏览器实现并提供的,浏览器会调用底层的、由其余语言(C++)实现并封装好的接口来完成任务;一样,在node中,也是V8引擎负责解释javascript,而你在javascript调用的浏览器提供的接口就不能用了,由于它脱离了浏览器的环境,可是由于你在node环境中,你就可使用node提供的由C++语言实现的、由javascript封装好的各类接口来完成后端任务。浏览器提供的API用于处理前端任务,好比弹个窗,换个主题,处理用户操做等,而node由于服务后端,所以提供的API则用来处理后端任务,好比响应请求,读取文件等,这些API由不一样的模块提供。由于关注领域不同,所以所作的任务就不同,提供的API就不同,可是原理、相关实现大体与浏览器端相同。java
从浏览器到node这一块若是想了解更多,推荐IBM的文章node.js究竟是什么?node
node架构分为三层(参考连接):git
图片来源github
日常咱们用到的也就是第一层node各个模块实现的接口。chrome
那他们之间时如何协做的呢数据库
程序启动,V8引擎会首先解析javascript代码,经过Node bindings来调用C/C++库。执行到当前事件时,会把事件放在调用堆栈(stack和heap)处理(能够理解为放进一个工做空间,如上图),在堆栈中的任何I/O请求都会交给libuv来处理,libuv维持一个线程池,里面是一些工做线程(以下图),请求会调用这些线程来完成任务,这些线程则调用底层的C/C++库。完成时,libuv再把结果返回事件队列等待主线程执行。在此期间,主线程继续执行其余任务。
单线程的意思就是只在一个线程上运行javascript。首先,javascript 在浏览器端是单线程的,这是为了不多线程产生任务冲突的状况;其次,java和PHP这类多线程后端语言,为避免同步I/O阻塞,每处理一个链接都会产生一个新线程,这样的话在遇到大量并发请求时就会受到物理内存的限制。node 延续了浏览器端单线程javascript,只用一个主线程执行javascript,不断循环遍历事件队列,执行事件。事实上,主线程发出的I/O请求,都会交给其余线程去完成,其余线程完成后悔返回结果放到事件队列。在此期间,主线程会继续执行其余任务,也就是在交给libuv后直接返回,继续执行下面的任务,主线程只负责循环执行事件队列,所以这种模式称为非阻塞型I/O,性能很好,适用于处理大量并发请求,还能简化开发。
仍是跟浏览器的差很少。总的来讲就是,浏览器端把鼠标点击、键盘按键等定义为事件,而node把网络请求、I/O操做等也看做事件,严格来讲,一切动做都是事件,这就是事件驱动的思想。在程序启动时,便进入事件循环,不断遍历执行事件队列中产生的事件,而在执行过程当中,又会产生新的事件,所以称为事件循环。主线程执行事件时,遇到麻烦的I/O请求会交给libuv来调度其余工做线程来帮忙,忙完后就会造成事件返回结果到事件队列等待主线程处理。在此期间,主线程会继续执行其余任务。
mbp 曾经作过一个巧妙的比喻,把 Node.js 当作一家餐厅。我在此借用下他的例子,稍做修改来阐述下 Node.js 的执行状况:
把 Node.js 应用程序想象成一家星巴克,一个训练有素的前台服务生(惟一的主线程)在柜台前接受订单。当不少顾客同时光临的时候,他们排队(进入事件队列)等候接待;每当服务生接待一位顾客,服务生会把订单告知给经理(libuv),经理安排相应的专职人员去烹制咖啡(工做线程或者系统特性)。这个专职人员会使用不一样的原料和咖啡机(底层 C/C++ 组件)按订单要求制做咖啡或甜点,一般会有四个这样的专职人员保持在岗待命(线程池),高峰期的时候也能够安排更多(不过须要在一早就安排人员来上班,而不能中午临时通知)。服务生把订单转交给经理以后不须要等着咖啡制做完成,而是直接开始接待下一位顾客(事件循环放进调用堆栈的另外一个事件),你能够把当前调用堆栈里的事件当作是站在柜台前正在接受服务的顾客。
当咖啡完成时,会被发送到顾客队列的最后位置,等它移动到柜台前服务生会叫相应顾客的名字,顾客就来取走咖啡(最后这部分在真实生活中听起来有点怪,不过你从程序执行的角度理解就比较合乎情理了)。
——By Amio
若是你想进一步了解javascript 事件驱动机制,推荐深刻理解 javascript 事件循环机制
node 模块机制是CommonJs 的实现。起初,javascript 标准一片混沌,并无其余成熟语言(例如C++)的模块机制、标准库、接口等,为了让javascript 具有开发大型应用的能力,为了让 javascript 能在后端运行,CommonJS 就制定了javascript 模块规范。node 借鉴了这个规范,让javascript 以模块形式组织起来。模块机制是一个成熟语言必备的,一个模块表明一个功能的封装,它就像搭积木同样,不一样模块能够衔接在一块,使语言具备极强的可扩展型。node 模块机制同时制定了模块规范,能让全球的开发者均可以在node官网上传本身的包。此外,node 社区又实现了node 包管理器npm,使用npm能够轻松管理各类包。
node 的模块分为核心模块和用户模块,前者是底层的、自带的,后者是第三方。
核心模块有Global(全局对象)、Http、fs(文件系统)、Buffer、Stream、Events、URL、path等,这些模块提供了后端服务的基本功能,都提供本身关注功能的API。
在使用模块时,require 便可。但在require背后,node 有一套寻找模块的机制:
从上图能够看到,node 优先从缓存区读取,缓存区有直接读取,没有则加载并缓存,这样作不用一遍一遍去找了,很是高效。node 在缓存区没有发现模块时,会分析require 的路径和文件后缀,node 有个模块路径的查找策略,咱们能够在名为module_paths
的js文件里console.log(module.paths)
而后node module_paths.js
运行来间接查看node 寻找文件模块的具体文件的方式:
[ '/home/username/nodeProject/node_modules',
'/home/username/node_modules',
'/home/node_modules',
'/node_modules' ] //Linux下的数组输出(/home/username因电脑不一样而异)
[ 'c:\\nodeProject\\node_modules', 'c:\\node_modules' ] //Windows复制代码
也就是按照下面的顺序:
这些顺序都是在查找缓存以后的。
在找到模块后,node 将在引入以前对这个模块进行编译执行,编译成功后会缓存,执行的结果会返回给调用者。
有了node 自带核心模块的基础功能,就能够进一步封装更强大、容易操做的功能了,就像jQuery 对于javascript 基础API 同样,node 社区也诞生了像 Express、KOA等框架来构建node.js程序
这些框架的详情移步2017 Node.js 开发框架比较
另外,node 还能够链接MySQL,MangoDB进行数据库操做。
下面是使用express 脚手架生成的基本 node应用结构:
.
├── app.js //程序入口
├── bin
│ └── www //二机制文件
├── package.json //项目配置文件
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js //路由文件入口
│ └── users.js
└── views
├── error.jade //界面模板
├── index.jade
└── layout.jade复制代码
如今使用 node做为后端语言一般都要配合类库和框架使用。
node 的单线程、非阻塞型特色让它很是适合高并发的应用,适合处理大量重复的、简单的逻辑,适合构建Rest/JSON API服务;同时,也正是由于这些特性,node 不适合CPU使用率较重、IO使用率较轻的偏计算应用。缺点是由于单线程,一个进程挂就全挂了,可靠性低,但这是能够避免的。node 更多的应用是在前端、中间件、先后端分离等。
因为 node 的诸多优势,如今愈来愈多大公司开始使用node、深度使用node。
node 的核心概念、思想远不止这么多,应用更是多了去了,无奈本人水平有限,只能说个浅层,还有不少像进程管理、异步编程、异常调试、部署、性能调优、与集群、CDN协调等都值得深刻探索一下。不管如何,node 是让javascript 迈向企业级开发语言重要的一步(也许已是了),前端工程师从未像如今这样的powerful,能作的事情愈来愈多,所能涉及的领域也愈来愈多。前端这行愈来愈使人兴奋了。