node.js

使用node的REPL模式

REPL(Read-eval-print loop)输入-求值-输出循环

进入的方式就是 命令行  下进入 输入node进入REPL模式

建立HTTP服务器

node.js是为网络而诞生的平台,node.js将“http服务器”这一层抽离,直接面向浏览器用户

使用node.js建立htpp服务器

var http=require('http');
http.createServer(function(req,res){
    res.writeHead(200,{'contet-Type':'text/html'});
    res.write("<h1>jiasjia</h1>");
    res.end('<p>jiasjia</p>');
}).listen(3000);
console.log("http server is listing at port 3000")
在浏览器输入local:3030

页面上会显示  

jiasjia 

 jiasjia

程序运行的原理:

对所有http请求答复同样的内容并监听了3000端口,在终端运行这个脚本时,我们会发现它并不像hello Word一样结束后立即退出,而是一直等待,知道按下ctrl+c才会结束

使用supervisor

node.js只有在第一次引用到某部分时才会去解析脚本文件,以后都会直接访问内存,避免重复载入,这种方式有利于提高性能,却不利于开发,因此,我们在开发过程中总是希望修改后就看到效果,而不是每次都得终止进程并重启这就是supervisor的作用

npm install -g supervisor

安装了以后当代码被改动时,运行的脚本会被终止,然后重新启动

异步时I/O与事件式编程

node.js最大的特点就是异步时I/O与事件紧密结合的编程模式,这种这种模式下控制流很大程度上要依靠事件和回掉函数来组织,一个逻辑单元拆分为若干单元

1、阻塞与线程

同步式i/o:线程在执行中如果遇到磁盘读写或网络通信(I/O)操作,通常都需要消耗较长的时间,这时操作系统会剥夺这个线程的cpu执行权,使其暂停执行,同时资源会让给其他的工作线程。这就是阻塞的式i/o

异步式i/o:则针对所有I/O操作不采用阻塞的策略。当线程遇到I/O操作时,不会以阻塞的方式等待I/O操作完成或数据的返回,而是将I/O请求发送给骚做系统,继续执行下一条语句。当操作系统完成I/O操作时,以事件的形式通知I/O操作的线程,线程会在特定的时候处理这个事件,为了处理异步I/O,线程必须有事件循环,不断的检查有没有未处理的事件node.js_第1张图片

2、回调函数

var fs=require('fs');
function  aa(err,data){

        if(err){
            console.log(err);
        }
        else{
            console.log(data)
        }

}
fs.readFile('file.txt','utf-8',aa);
console.log('end.')
会输出

end.

文件里边的内容

与料想的会先输出文本里边的内容不一样,而是先输出了end.

这里aa就是一个回调函数,在readFile调用时所做的工作就是把I/O请求发送给操作系统,然后立即执行跟后面语句,执行完了以后进入事件监听环节,当fs收到I/o请求完成的事件时,事件循环会主动调用回调函数以完成后续的工作,这就是为什么我门先看到end,后看到文件中的内容的原因

3、事件

node.js所有的异步I/O操作在完成时都会发送一个事件到事件队列,事件由EventEmitter对象提供的。

var EventEmitter=require('events').EventEmitter;
var event=new EventEmitter();
event.on('some_event',function(){
    console.log('some_event occurd');
});
setTimeout(function(){
    event.emit('some_event');
},1000)
运行的结果在控制台隔了一秒之后   输出some_event occured

原理:event对象注册了事件some_event的一个监听器,setTimeout在1秒以后向event对象发送事件some_event  此时就会执行some_event中的内容

4、模块和包

模块(module)和包(Package)是node.js的重要支柱,开发一个具有一定规模的程序不可能只使用一个文件,通常把各个功能拆分、封装、组合起来,模块就是为了实现这种方式而诞生的。node.js提供了require函数来实现来调用其它模块,而且模块都是基于文件的

什么是模块?

模块是Node.js应用程序的基本组成成分,文件和模块是一一对应的

创建模块

创建模块:node.js提供了exports和require两个对象,exports是模块公开的接口,require用于从外部获取一个模块的接口,也就是获取该模块的exports

自定义一个模块  first.js

var name;
exports.setName=function(thyName){
    name=thyName;
};
exports.sayHello=function(){
    console.log(name);
}
getFirst.js使用first.js

var myModule=require('./first');
myModule.setName('skao');
myModule.sayHello();
node  getFirst.js会输出skao

node的单次加载

上述实例类似于创建了一个对象,但是实际上与对象有本质上的区别因为require不会重复加载,也就是无论调用多少次require,获得的模块都是同一个

var myModule=require('./first');
myModule.setName('skao');
var myModule1=require('./first');
myModule1.setName('new');
myModule.sayHello();
发现输出的是new  这是因为myModule1和myModule2这两个变量指向的是同一个实例,2的name会把1的name覆盖掉

实现封装

封装了一个Hello的类

function Hello(){
    var Name;
    this.setName=function(nn){
      Name=nn;
    }
    this.hello=function(){
        console.log(Name);
    }

};
module.exports=Hello;
这时接口对象输出的就是Hello对象本身,而不是原来的exports

使用的方法

var myModule=require('./first');
myModule=new myModule();
myModule.setName('sasa');
myModule.hello();
创建包

包是模块基础上更深一步的抽象,node.js的包类似于c/c++的函数库或者java的类库。它将每个独立的功能封装起来,用于发布、更新、依赖和版本控制。

node.js的包是一个目录,其中包括json格式的包说明文件package.json。

1、作为文件夹的模块

新建一个文件夹somepackage里边包含一个文件index.js里边的内容

exports.hello=function(){
    console.log('hello');
}
在文件夹的外边新建一个文件getpackage.js

var somePackage=require('./somepackage');
somePackage.hello();
控制台输出  hello

2、package.json  在somepackage文件夹下

在package.json中写

{
   "main":"./lib/interface.js"
}

运行getpackage.js依然会得到结果,这是因为在调用某个包时,会首先检查包中package.json文件的main字段将其作为包的接口模块,如果没有会尝试找index.js

或者index.node作为包的接口

package.json应该要包含以下字段

node.js_第2张图片

node.js的包的管理器

npm install express

在使用npm安装包的时候,有两种模式本地模式和全局模式

一般来说安装的时候都使用到全局模式,因为许多程序都有可能用到它,为了减少副本而使用了全局模式,全局模式会注册path环境变量

全局对象

全局变量的属性可以在程序的任何地方访问,浏览器的window对象,Node.js中的全局对象就是global,所有全局变量都是global对象的属性

比如console process

process

 process是一个全局变量,即golbal对象的属性,它用于描述当前Node.js进程状态的对象,提供了一个与操作系统的简单的接口


node argv.js

输出[ 'node', 'D:\\work\\nodeWorkspace\\argv.js' ]

node argv.js 1991 name=byvoid --v 'Carbo Kuo'

输出

[ 'node',
  'D:\\work\\nodeWorkspace\\argv.js',
  '1991',
  'name=byvoid',
  '--v',
  '\'Carbo',
  'Kuo\'' ]


在argv.js里边写

process.stdout.write('sasasa');

会输出sasasa


process.stdin.resume();
process.stdin.on('data',function(data){
    process.stdout.write('read form console'+data.toString());
})
控制输入什么就会输出什么

node.js进程只有一个线程,node.js适合i/o密集型的应用而不是计算密集型的应用,在任何时刻都只有一件事在进行,node.js的一个编程原则就是尽量缩短每个事件的执行时间,这个方法就是把一个复杂的工作拆散

console

console.log()

console.error()  向标准错误流输出

console.trace() 向标准错误刘输出当前调用栈

常用工具util

1、util.inherits

实现对象间原型继承的函数,javascript没有提供对象继承语言级别特性,而是通过原型复制来实现的

var util=require('util');
function Base(){
    this.name='base';
    this.base=1991;
    this.sayhello=function(){
        console.log(this.name);
    }
}
Base.prototype.showName=function(){
    console.log(this.name);
}
function Sub(){
    this.name='sub';
}
util.inherits(Sub,Base);  //sub继承了Base类的属性和方法
var ob=new Base();
ob.sayhello();       //base
ob.showName();      //base
var os=new Sub();
os.showName();     //sub
os.showName();      //sub
console.log(os);
注意:Sub仅仅继承的了在原型中的定义的函数,而构造函数内部创造的base属性和其他在构造函数声明的方法都不会被继承

2、util.inspect

这个方法是将任意一个对象转换为字符串的方法,一般用来调试,至少要接受一个参数object(要转换的对象)

var util=require('util');
function Person(){
    this.name='bb';
    this.toString=function(){
        return this.name;
    }
}
var obj=new Person();
console.log(util.inspect(obj));
console.log(util.inspect(obj,true));
运行结果

{ name: 'bb', toString: [Function] }
{ name: 'bb',
  toString:
   { [Function]
     [length]: 0,
     [name]: '',
     [arguments]: null,
     [caller]: null,
     [prototype]: { [constructor]: [Circular] } } }

事件驱动events

events模块是node.j最重要的模块,原因是node本省架构就是事件式的,就是events提供了接口。events模块不仅用于用户代码与Node.js下层事件循环的交互,还几乎被所有的模块依赖

1、事件发生器

events模块只提供了一个对象:events.EventEmitter。EventEmitter的核心就是事件发射与事件监听器功能的封装。EventEmitter的每个事件由一个事件和若干个参数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter支持若干个事件监听器。当事件发射时,注册到这个事件的监听器就被依次调用,事件参数作为回调函数来处理

var eventem=require('events').EventEmitter;
var events=new eventem();
events.on('some_events',function(aa,bb){
    console.log('listener1',aa,bb);
})
events.on('some_events',function(aa,bb){
    console.log('listener2',aa,bb);
})
events.emit('some_events','bb','1221');
给some_event注册了两个事件

会输出

listener1 bb 1221
listener2 bb 1221

EventEmitter常用的API

1、EventEmitter.on(event,listener)为指定事件注册一个监听器。接受一个字符串event和一个回调函数listener

2、EventEmitter.emit(event,[参数1],[参数2])发射event事件,传递若干可选参数到事件监听器的参数表

3、EventEmitter.once(event,listener)为指定事件注册一个单次监听器,监听器最多只能触发一次,触发后立刻解除该监听器

4、EventEmitter.removeListener(event,listener)移除指定事件的摸个监听器

var eventem=require('events').EventEmitter;
var events=new eventem();
function cc(aa,bb){
    console.log('listener1',aa,bb);
}
events.on('some_events',cc);
events.removeListener('some_events',cc);   
events.on('some_events',function(aa,bb){
    console.log('listener2',aa,bb);
})
events.emit('some_events','bb','1221');
运行程序只会输出一次   listener1 bb 1221

5、EventEmitter.removeAllListener([event])移除所有事件的监听器

var eventem=require('events').EventEmitter;
var events=new eventem();
function cc(aa,bb){
    console.log('listener1',aa,bb);
}
events.on('some_events',cc);

events.on('some_events',function(aa,bb){
    console.log('listener2',aa,bb);
})
events.removeAllListeners('some_events');
events.emit('some_events','bb','1221');
运行程序不会输出任何的信息

2、error事件

EventEmitter定义了一个特殊的事件error,它包含了“错误”的语义,我们在遇到异常通常会发射error事件。当error被发射时,EventEmitter规定如果没有响应的监听器,node.js会把它当作异常,退出程序并打印调用栈。我们一般要为发射error事件的对象设置监听器,避免碰到错误后整个程序崩溃

当这样使用的时候就会使程序崩溃

var eventem=require('events').EventEmitter;
var events=new eventem();
events.emit('error');
3、继承EventEmitter

大多数的时候我们不会直接使用EventEmitter对象,而是在对象中继承他。包括fs、net、http在内的,只要支持事件响应的核心模块都是EventEmitter的子类

文件系统fs

fs模块是对文件操作的封装、提供了文件的读取、写入、更名、删除、遍历目录、连接等POSIX文件系统操作,与其他模块不同的是fs模块中所有的操作提供了异步的和同步的两个版本

1、fs.readFile

fs.readFile(filename,[encoding],[callback(err,data)])是最简单的读取文件的函数,他必须接受一个必选参数,表示要读读取的文件名。

参数encoding是可选的,

参数callback的两个参数err,data       err表示有没有错误发生   data是文件内容

如果指定了encoding,data是一个解析后的字符串,否则data将会是以Buffer形式表示的二进制数据

var fs=require('fs');
fs.readFile("file.txt",'utf-8',function(err,data){
    if(err){
        console.log(err);
    }
    else{
        console.log(data);
    }
});
会输出  文件中的内容:赵文娟

2、fs.readFileSync

参数列表和fs.readFile是一致的,但是它是fs.readFile的同步的版本,读取到的内容会以函数的返回值的形式返回。

var fs = require('fs');
var contentText = fs.readFileSync('file.txt','utf-8');
console.log(contentText);
3、fs.open

fs.open(path,flags,[model],[callback(err,data)])path为文件的路径,flags可以是以下值

node.js_第3张图片

4、fs.read

fs.read(fd,buffer,offset,length,position,[callback(err,bytes,buffer)])是read函数的封装,相比fs.readFile提供了更底层的接口。

fs.read的功能是从指定的文件描述符fd中读取数据并写入buffer指向的缓冲区对象。offset是buffer的写入偏移量。

length是要从文件中读取的字节数

position是文件读取的起始位置,如果position的值为null,则从开始读

回调函数的  bytesRead和buffer分别表示字节数和缓冲区对象

var fs = require('fs');
fs.open('file.txt','r',function(err,fd){
    if(err){
        console.log(err);
        return ;
    }
    var buf=new Buffer(8);
    fs.read(fd,buf,0,8,null,function(err,bytesRead,buffer){
        if(err){
            console.log(err);
            return ;
        }
        console.log('bytesRead'+bytesRead);     //读取的字节数
        console.log(buffer);                 //输出缓冲区
    })
})
HTTP服务器与客户端

node.js标准库提供了http模块,其中封装了一个高效的HTTP服务器和一个简易的HTTP客户端。http.server是一个基于事件的HTTP服务器,它的核心由Node,js下层的c++部分实现,接口由javaScript实现

1、http服务器

http.server是http模块中的服务器对象,用Node.js做的所有基于HTTP协议的系统、网站、社交应用甚至代理服务器,都是基于http.server实现的。

http.Server的是一个基于事件的http服务器,所有的请求都被封装为独立的事件,开发者只需要对它的事件编写响应函数即可实现HTTP服务器的所有功能。继承自EventEmitter,提供了以下几个事件。

request:当客户请求到来时,该事件被触发,提供两个参数req和res,分别是http.SeverRequest和http.ServerResponse的实例。表示请求和响应的消息

connection:当TCP连接建立时,该事件被触发,提供了一个参数socket,为net.socket的实例。connection事件的粒度大于request,因为客户端在Keep-Alive模式下可能在同一个连接内发送多次请求

close:当服务器关闭时,该事件被触发

你可能感兴趣的:(node.js)