node.js不是一种独立的语言,与php既是语言也是平台不一样,也不是JavaScript的框架,更不是浏览器的库。node.js是一个让JavaScript运行在服务端的开发平台。php
JavaScript是由客户端而产生,node.js为网络而生html
具备复杂逻辑的网站node
基于社交网站的大web的应用c++
web scoket服务器web
TCP/UDP套接字应用程序chrome
命令行工具npm
交互式终端程序编程
node.js最大的特性就是采用异步式I/O与事件驱动的架构设计。对于高并发的解决方案,传统的架构是多线程模型,也就是为每一个业务逻辑提供一个系统线程,经过系统线程切换来弥补同步式I/O调用时的事件开销。node.js使用的单线程模型,在执行的过程当中会维护一个事件队列,程序在执行时在进入时间循环等待下一个事件到来。json
普通:res = db.query("select * form user")数组
res.output();
node.js: res = db.query("select * form user",function(res){
res.output();
})
程序会自动往下执行
四、浏览器引擎革命
Google chrome的引擎是V8,node.js的引擎引用的就是V8,因此它快
五、部署node.js的环境
node.js官方,http://nodejs.org 下载安装包,安装后,打开cmd的的dos窗口,运行node
打开一个文本编辑器,其中输入console.log("Hello World"),并保存为test.js
打开dos窗口进入该文件的目录运行 node test.js,执行则能够看到输出的Hello World
node -v 输出版本号
node -e eval script eval("console.log('哈哈')") 例:node -e "console.log('哈哈')";直接执行
node 直接进入编译模式 console.log("111") 第一行是输出,第二行是返回值
创建一个app.js
1 var http = require("http"); 2 http.createServer(function(req,res){ 3 res.writeHead(200,{'Content-Type':'text/html'}); 4 res.write('<h1>Node.js</h1>'); 5 res.end('<p>PCAT</p>'); 6 }).listen(3000); 7 console.log('HTTP server is listening at port 3000');
接下来,node app.js 打开浏览器访问http://localhost:3000便可,这样就部署了一个web
npm install supervisor -g(在nodejs\node_modules\npm目录下)安装supervisor来控制调试代码,不须要每次中止重启node.js的服务
使用supervisor app.js启动
node.js最大的特性就是异步式I/O与事件紧密结合的编程模式。这种模式与传统的同步式IO线性的编程思路有很大的不一样,由于控制流很大程度上要靠事件和回调函数来组织,一个逻辑要拆分为若干个单元格
线程在执行中若是遇到磁盘读写或网络通讯,一般要耗费较长时间。这时操做系统会剥夺这个线程的CPU控制权,使其暂停执行,同时把资源让给其余的工做线程这种线程调度方式称为阻塞,当I/O操做完毕时,操做系统将这个线程的阻塞状态解除,回复其对CPU的控制权,令其继续执行
针对全部I/O操做不采用阻塞策略,当线程遇到I/O操做时,不会以阻塞的方式等待I/O操做的完成或数据的返回,二只是将IO请求发送给操做系统,继续执行下一条语句,当操做系统完成IO操做时,以事件的形式通知执行IO操做的线程,线程会在特定时候处理这个事件,为了处理异步IO,线程必须有事件循环,不断地检查有没有未处理的时间,依次予以处理
非阻塞模式下,一个线程永远在执行计算操做,这个线程所使用的CPU核心利用率永远是100%,IO以事件的方式通知
阻塞模式下,多线程每每能提升系统吞吐量,由于一个线程阻塞还有其余线程在工做,多线程可让CPU资源不被阻塞中的线程浪费
同步式IO(阻塞式)
利用多线程提供吞吐量
经过事件片分隔和线程调度利用多核CPU
须要由操做系统调度多线程使用多核CPU
难以充分利用CPU资源
内存轨迹大,数据局部性弱
符合线性的编程思惟
异步式IO(非阻塞)
单线程便可实现高吞吐量
经过功能划分利用多核
能够将但相处绑定到单核CPU
能够充分利用CPU资源
内存轨迹小,数据局部性强
不符合传统编程思惟
1 var fs = require("fs"); 2 var data = fs.readFile("file.txt","UTF-8",function(err,data){ 3 if(err){ 4 console.log("read file err"); 5 }else{ 6 console.log(data); 7 } 8 }) 9 console.log("end,");
结果:end
文件内容
1 var fs = require("fs"); 2 var data = fs.readFileSync("file.txt","UTF-8"); 3 console.log(data); 4 console.log("end");
结果:文件内容
end
调用时所作的工做只是将异步式IO请求发送给了操做系统,而后当即返回并执行后面的语句,执行完之后进入事件循环监听事件,当fs接收到IO请求完成的事件时。事件循环会主动调用回调函数完成后续工做。同步则是阻塞等待文成后,继续执行
//声明事件对象 var EventEmitter = require("events").EventEmitter; var event = new EventEmitter(); //注册事件 event.on("some_event",function(){ console.log(111); }) //触发事件 setTimeout(function(){ event.emit("some_event"); },3000)
node.js在何时进入事件循环呢
node.js程序是由事件循环开始,到事件循环结束,全部的逻辑都是事件的回调函数
如何使用自定义事件呢?
事件的回调函数在执行过程当中,可能会发出IO请求或直接发射(emit)事件,执行完毕后再返回事件循环
概念:模块和包是node.js最重要的支柱。开发一个具备必定规模的程序不愿只用一个文件,一般须要把各个功能拆分、分装、而后组合起来。模块正是为了实现这种方式而诞生,在浏览器JavaScript中,脚本模块的拆分和组合一般使用html的script标签来实现,node.js提供了require函数来调用其余模块,并且模块都是基于文件,模块和包的区别是透明的,常常不作区分
模块和文件是一一对应的。一个node.js文件就是一个模块,这个文件多是JavaScript代码、json或者编译过的c/c++扩展。
var http = require("http"),其中http是node.js的一个核心模块,经过require函数获取这个模块,而后使用其中的对象
node.js提供了exports和require两个对象,其中exports是模块公开的接口,require用于从外部获取一个模块的接口,即获取模块的exports对象
module.js
1 var name; 2 exports.setName = function(theName){ 3 name = theName; 4 } 5 exports.sayHello = function(){ 6 console.log("hello"+name); 7 }
getModule.js
1 var myModule = require("./module"); 2 myModule.setName("wang er"); 3 myModule.sayHello();
上面的例子相似建立一个对象,但实际上和对象又有本质的区别,由于require不会重复加载模块,不管调用多少次require,获取的模块都是同一个
getModule2.js
1 var myModule1 = require("./module"); 2 myModule1.setName("wang wu"); 3 var myModule2 = require("./module"); 4 myModule2.setName("hello world"); 5 myModule1.sayHello();
有时咱们想把一个对象封装到模块中
定义模块:singleobject.js
1 function hello(){ 2 var name; 3 this.setName = function(theName){ 4 name = theName; 5 } 6 this.sayHello = function(){ 7 console.log("hello"+name); 8 } 9 }; 10 module.exports = hello;
引入模块使用:getsingleobject.js
1 var hello = require("./singleobject"); 2 var he = new hello(); 3 he.setName("sugar"); 4 he.sayHello(); 5 var he2 = new hello(); 6 he2.setName("txy"); 7 he2.sayHello();
exports自己仅仅是一个普通的空对象,即{},它是专门用来声明接口
2.一、包的概念
包是在模块基础上更深一步的抽象,node.js的包相似于c/c++的函数库或者Java的类库,它将某个独立的功能封装起来,用于发布、更新、依赖管理的版本控制。开发了npm来解决包的发布和获取需求。
2.二、如何建立一个包
commonJS规范的包具有如下特征:
package.json必须在包的顶层目录下
二进制文件应该在bin目录下
JavaScript代码应该在lib目录下
文档应该在doc目录下
单元测试应该在test目录下
Node.js对包要求没有那么严格,只要顶层目录下有package.json,并符合基本规范便可
(1)做为文件夹的模块
somepackage文件夹(最简单的包,就是做为文件夹的模块)
建立一个文件夹somepackage,里面有一个index.js,里面提供一个方法sayHello()
var somepackage = require("./somepackage");
somepackage.sayHello();
使用这种方法能够把文件夹封装成一个模块,即包。包一般是一些模块的集合,在模块的基础上提供了更高层的抽象,至关于提供了一些固定接口的函数库,经过定制package.json,咱们能够建立更符合规范的包进行发布。
(2)package.json
在somepackage文件夹下,咱们建立一个package.json的文件,内容{"main":"./lib/index.js"}
node.js在调用某个包时,会检查包中package.json文件的main字段,将其做为包的接口模块,若是package.json或main字段不存在,会寻找index.js或index.code做为包的接口
package.json的规范属性:
name:包的名称,必须是惟一
description:包的简要说明
version:符合语义化版本识别规范的版本字符串
keywords:关键字数据,一般用于搜索
maintainers:维护者数组,每一个元素要包含name、email、web可选字段
contributes:贡献者数组,格式与maintainers相同。包的做者应该是贡献者数据的第一个元素
bugs:提交bug的地址,能够是网址或者是电子邮件地址
licenses:许可证数组,每一个元素要包含type、url字段
repositories:仓库托管地址数组,每一个元素要包含type、url、和path、字段
dependencies:包的依赖,一个关联数组,由包名称和版本号组成