Node.js学习

作者: 郑伟的菜园子 | 来源:发表于2016-06-01 10:04 被阅读131次

    主线:Node.js是什么 --> Node.js的组成 --> Node.js的特点 --> Helloworld例子 --> 模块 --> 核心模块 --> 本地模块 --> 包 --> 包管理器 --> 非阻塞、单线程、事件驱动 --> 回调函数 --> Node的应用

    Node是什么东西呢?首先看他的名字,Node.js,初看起来的话有的人以为这个玩意有可能是像jQuery一样,也是一个库、框架,但其实不是的,Node.js是一个让JavaScript运行在服务端的平台,或者说Node.js是一个可以让JavaScript运行在非浏览器环境下的工具,Node.js采用的是号称是世界上最快的chrome v8引擎,是由二部分组成的,由Core JavaScript和Node Standard Library组成的,Core JavaScript其实说白的指的就是ECMAScript,也就是说只包含了我们在浏览器端的js脚本中的ECMAScript,排除了我们文档对象模型,也就是DOM,还有浏览器对象模型,也就是BOM,有的人以为Node是不是有兼容性问题呢?Node是没有兼容性问题的,因为我们学过客户端浏览器的js脚本也应该明白其实我们经常说的js的兼容性问题指的其实就是我们的DOM和BOM方面的兼容性问题,那什么是Node Standard Library,这个就类似于我们C标准库,或者C++的标准扩展库的玩意,Node.js的特点就是非阻塞异步事件驱动,Node.js让我们的JavaScript哜身于我们的脚本世界的第一等公民,我们首先来看第一个例子,helloworld,这个helloworld看起来比其他的语言好像要更复杂?不过我们可以看一下这6行代码实现的功能,它实现了一个简单的服务器,Node.js的支柱之一就是模块,所以我们首先要学习的就是模块,那么什么是模块呢?模块其实就是一个js的文件,在我们的客户端浏览器中,我们想要实现一个css文件嵌入引入另一个css文件,我们可以使用@import指令,但是在我们js中,如果要想引入另一个js,就不是那么容易了,当然了也不是说不可以实现,我们可以通过createElement,创建一个script标签,然后appendChild到我们的html当中就可以实现了,但是不管怎么样,实现起来其实不是那么容易的,我们的Node一解决掉了这个问题,我们的Node里面,直接一个js文件就是一个模块,我们创建好二个js文件,那我们怎么才能在一个js文件中引入另外一个js文件呢?我们可以通过一个叫require的函数来引入就可以了,我们可以把每一个模块当成一个更大的对象,他们最终都会暴露出来一些属性和方法的,我们是通过一个叫exports,或者module.exports来暴露出来属性和方法的,模块分为二种类型,一种是核心模块,常见的核心模块有http模块、os模块也就是操作系统相关的模块、fs模块也就是file system模块处理与文件操作相关的东西、util模块工具类的东西,另外一种就是本地模块,所谓的本地模块就是我们可以自己来创建一个自己的模块,与模块相比更大的一个单元就是包,什么是包呢?我们可以想一下,我们可以把一个模块想成我们的一个文件,我们可以把包想像成一个文件夹,也就是说我们可以用一个文件夹把一堆的类似的功能的文件放在一起打包,说到包,我们一般的除了自己创建的包以外,更重要的其实是一些第三方的包,在npm.org这个网站上,有大量的差不多有几万个别人实现好的第三方的包供我们要吧使用,具体是怎么使用呢?我们的Node为了方便我们使用第三方的包,就开发了一个工具就包管理工具,也就是我们的npm,我们可以简单的来看一下这个东西是怎么用的,我们安装有二种方式,一种是全局安装,一种是本地安装,这个和其他语言可能不是一模一样的,比如像python,ruby,全局安装的包一般适用于命令行操作的,比如像我们lessc,另外一种本地的包一般的用于我们当前要做的一些项目里面,当然了,如果只是有这些东西的话,那Node.js是没啥大的特点的,因为这些东西其实在其他语言里像python,ruby里面早就有了,Node.js最大的特点其实是异步非阻塞和事件编程模块,这个应该是完全颠覆性设计,和其他的语言有很大的区别,比如下面是二个例子,希望大家能看懂这个例子,假设我们实现的是同步的IO,我们要查询的是SQL语句,通常我们会写出下面这样的代码,比如说python,比如php,都是这样的形式,就是说先用db.query然后一个SQL查询,就会有阻塞等待数据库把结果返回以后存储到一个res的变量当中,但是下面这个才是Node的真正的写法,这个是用了异步IO的方式,可以看出,其实这一条语句,其实这是一条语句,他是产生了这样一个SQL查询,并且在第二个参数中放了一个函数,这个函数被称为回调函数,也就是说这条语句执行完以后,并不会直接执行res.auto,他会继续向后执行,等到什么时候会执行里面的内容呢?等到我这个数据库把消息返回了,然后再通过事件循环,进入回调函数,再把查询的结果打印出来,这是异步IO的模式,然后再解释一下什么是同步,什么是异步,程序在执行IO操作的时候可能要花费很长的时间,可能会长达数十万或数亿多的指令周期,但是你执行一次javascript语句可能只需要花费几百或上千个指令周期,当然也许经过优化之后可能只需要几十个,所以说遇到IO之后是非常浪费时间的,操作系统和CPU是通过中断的方式来实现异步的调度方法,也就是说当进程发起IO请求时,操作系统会挂起当前进程,然后将CPU的控制权让给其他部分的进程,当IO完成以后,操作系统才会使原来的进程恢复继续执行,同时你就可以访问刚才IO操作的结果,这个请求的方式我们称之为同步IO,或者阻塞式IO,但是在Node中IO的模式我们使用的是异步的IO,或者叫非阻塞IO,这个指的是当进程发起IO请求之后,就立刻返回并继续执行其他的指令,然后通过其他的手段来通知IO已经操作完成了,接下来再来处理IO操作完成以后的逻辑代码,然后当非阻塞IO发起的时候呢,进程不会进入阻塞状态,而是继续执行事件的其他部分,然后进入事件循环处理其他事件,这里面提到了一个事件和事件循环的概念,在Node中所有的计算逻辑操作都会被抽象成一个事件,然后整个程序就是一个事件循环,事件循环会不断的处理一个叫事件队列的东西,就是说我最开始的时候有一个事件,然后执行的过程中可能会发起一些请求,比如说IO请求,IO请求完成以后,会在事件队列中加入事件队列,等待进程以后进入事件循环之后进行处理,这是基于事件循环的处理模式,这种基于事件驱动的模式其实也是一种很经典非常常用的模式,比如qt,gtk,比如说鼠标点击是一个事件,比如说timer也是一个事件,事件的话就少不了有回调函数,所谓的回调函数指的是当我们的事件发生以后,然后Node为什么要使用这种晦涩难懂的编程模式呢?其实这是Node另外一个非常特殊的策略,它使用了单线程模式,我们首先来说一下阻塞模式的并发模型,比如说我们要开发一个web服务器,当然是要有并发要求的,可以让多个用户同时访问,不是说我处理完一个用户的请求再处理第二个用户的请求就完了,这样的话当用户一多起来,处理的速度就会非常的慢,当一个用户非常慢并且不断开连接的时候,其他的用户就会一直在等待,这样是不合理的,在阻塞模式下要想实现并发必须使用多线程,就是一个进程只能处理一项任务,我们要想提高CPU的吞吐量,必须要使用的是多线程,要使用可能比CPU核数量多得多的线程,这个要多多少呢,这个是不可预测的,比如说我们的一个逻辑,他要先计算一部分,然后再发起一个IO请求,比如说读一个文件或者写一个文件,或者说发起一个网络请求,接下来进入我们第二个计算的部分,要想实现并发,我们可以使用多线程的模式,它的执行可能会是一个这样的,假设我们是单个CPU,那么就是首先第一个 线程抢占了CPU进行计算,然后他到了IO请求阶段,进入 阻塞了,这时候CPU的控制权就会被出让出来了,然后这时候第二个线程就会抢占了CPU,然后进入IO,又堵塞了,然后再释放出cpu的控制权,线程3、线程4、线程5这样,然后中间可能会有一段空闲时间,然后等线程1的IO结束了,然后他发现CPU没有被占用,它就会去使用CPU进入计算,这样的基于计算和IO的并发抢占式模式,但是在非阻塞模型下,它的模型会是这样的,一个单线程的,计算1会发起一个异步的IO请求,这时候会直接再进入另一个计算1,可能会是另一个用户发起的计算1,然后发起第二个请求,然后等5个用户可能都发起完了,这时候正好第一个用户的计算结束了,然后我们这个事件循环就是单线程就会执行第一个用户发起的IO请求,我们在非阻塞模式下进程对CPU的利用从理论上来说是百分之百,这是理想情况下,单个线程就可以达到最大吞吐量,不需要多个线程,然后什么时候需要多线程呢?是我们有多核的时候,比如说我们有2个核我们就开2个线程,然后非阻塞比阻塞好在哪里呢?多线程听起来很快,但是其实没那么快,因为要进行切换,时间片切分会非常小的,每20ms切换一次站,对CPU缓存的利用率是非常不高效的,非阻塞也不是非常好的,会容易引起回调地狱,先读取第一个文件,然后再读取第二个文件,这是一个mongoDB的操作。Node基本我就介绍到这里,说了半天Node,Node到底有啥应用呢?首先,Node有许多第三方模块,比如说我们要做一个web做一个网站,可以使用express这个框架,然后生成html可以使用一个叫jade的模板引擎,生成css有less和stylus,用于压缩javascript有uglify,使用websocket有socket.io,SQL数据库有ORM,oAuth,守护进程,命令行解析,语法分析,包括,还有Node.js其实虽然和DOM没有关系,但是其实也可以处理,文件上传,语法高亮,解析markdown,编码转换图像处理,轻量级线程和协程,coffeescript,浏览器端的一些静态分析,谢谢大家,今天我对Node.js的介绍就到这里。

    相关文章

      网友评论

        本文标题:Node.js学习

        本文链接:https://www.haomeiwen.com/subject/aelhdttx.html