Node,js笔记

关于node的命令行

node -e 'js文本'    解析一段js文本

实时刷新:  npm install supervisor -g

      supervisor test.js

 

 

关于node的模块化:

node.js 不是一个框架,也不是一门语言,而是一个让javascriprt 运行在服务端的开发平台

在Node环境中,一个.js文件就称之为一个模块(module)。这种模块加载机制被称为CommonJS规范

在hello.js文件中:

function greet(name) {
    console.log(s + ', ' + name + '!');
}

function getsame() {
  console.log('function')
}
module.exports = {    // 导出模块
  getsame,
  greet
}

在main.js文件中:

var greet = require('./hello');   // 导入模块,相对路径

greet.greet('小妹')    // 调用greet模块中的方法

greet.getsame()

 

关于node的基本模块:

global :  全局对象,类似于window

console : 输出对象

process : 表示当前node的进程,可以通过它得到当前的工作目录、执行进程等

   process.cwd()   获得当前的工作目录

   process.chdir('路径')   切换当前工作目录

   process.on('exit' , function(){})   在node程序即将执行完退出时进行的回调

   process.nextTick()     在下一次事件循环中调用

process.nextTick(function () {     // 在下一个事件执行完之后执行
    console.log('nextTick');
});

console.log(console)   // 执行完后执行process.nextTick()

process.on('exit',function(code){    // 传入code 参数,表示执行结果
  console.log(code)
})

 util :实用工具

  util.inherits(fun1, fun2):实现两个对象之间的原型继承,推荐使用ES6的 class extends 代替

var util = require('util')

function fun1 () {
  this.name = 'fun1'
}

function fun2 () {
  this.name = 'fun2'
}

fun1.prototype.showName = function() {   // 定义原型方法
  console.log(this.name)
}

util.inherits(fun1,fun2)    // 使用inherits 进行原型继承

var test = new fun2();

test.showName();   // 调用继承过来的方法

   

  util.inspect(obj, [showHidden], [depth], [colors])  将一个对象转化为字符串,接收四个参数,后面三个为可选参数    

   showHidden: 布尔值,如果为true, 将输出更多详细信息

  depth: Num值,表示标识最大的递归层数,即打印到第几层

  colors:布尔值,如果为true,则打印出来的数据具备对应文本颜色(只有视觉效果作用)

var util = require('util')

function obj () {
  this.name = 'object'
  this.fun = function() {
    console.log(this.name)
  }
}

console.log(util.inspect(obj,true,3,true))   
// 输出 { [Function: obj]
// [length]: 0,
// [name]: 'obj',
// [arguments]: null,
// [caller]: null,
// [prototype]: obj { [constructor]: [Circular] } }

关于node的内置模块:

读写文件:fs

 fs : 文件系统模块,负责读写文件     fs模块同时提供了异步和同步(Sync)的方法

fs.readFile()     异步读取文件  ,传入文件路径、编码格式、回调函数
 
fs.readFileSync()  同步读取文件,传入文件路径、编码格式     如果同步读取文件发生错误,则需要用try...catch捕获该错误
 
  var fs = require('fs');

fs.readFile('test.txt','utf-8',function(err, data){ // 读取纯文本,传入文件路径、编码格式 if(err){ // 回调方法传入两个参数。err为失败信息,data为读取到的数据 console.log('读取出错了'+err) } else { console.log('读取的数据内容为:'+data) } }) fs.readFile('img.jpg',function(err, data){ // 读取二进制文件,传入文件路径,获得的data是一个Buffer对象 if(err){ console.log('读取出错了'+err) } else { console.log(data); // 输出<Buffer ff d8 ff e0 00 10 4a 46 49 ... > } }) var data = fs.readFileSync('test.txt','utf-8') // 同步读取文件,没有回调函数,直接返回结果 try { var data = fs.readFileSync('sample.txt', 'utf-8'); console.log(data); } catch (err) { // 出错了 }
 

Buffer对象就是一个包含零个或任意个字节的数组(注意和Array不同)

Buffer对象可以和String作转换,例如,把一个Buffer对象转换成String:

var text = data.toString('utf-8');

同时也可以把任意String转换成Buffer对象:

var buf = new Buffer('这是一个utf-8编码格式的纯文本文件','utf-8');
console.log(buf)   // 输出<Buffer e8 bf 99 e6 98 af e4 b8 80 ... >

fs.writeFile()  异步将数据写入文件  ,依次传入三个参数,分别为文件名、写入的数据、回调函数。回调函数只有成功与否一个参数,err 为 null 时表示成功    该方法写入的数据会替换原本的数据内容

fs.writeFileSync()  同步将数据写入文件

传入的数据是String,默认按UTF-8编码写入文本文件,如果传入的参数是Buffer,则写入的是二进制文件

var data = '这是新写入的数据内容'

fs.writeFile('test.txt',data,function(err){    // 该方法会直接替换原本文件内的数据
  if(err){
    console.log('数据写入失败,错误为:'+err)
  } else {
    console.log('数据写入成功')
  }
})

fs.readFile('test.txt','utf-8',function(err, data){
  if(err){
    console.log(err)
  } else {
    console.log(data)  // 输出'这是新写入的数据内容'
  }
})

fs.stat(),获得文件的信息,它返回一个Stat对象,记录文件或目录的详细信息,如文件大小、创建时间等    stat()也有一个对应的同步函数statSync()

fs.stat('test.txt', function (err, stat) {
    if (err) {
        console.log(err);
    } else {
        console.log('isFile: ' + stat.isFile());                    // 是否是文件:
        console.log('isDirectory: ' + stat.isDirectory());         // 是否是目录:
        if (stat.isFile()) {    
            console.log('size: ' + stat.size);                     // 文件大小:
            console.log('birth time: ' + stat.birthtime);          // 创建时间, Date对象:
            console.log('modified time: ' + stat.mtime);           // 修改时间, Date对象:
        }
    }
});

依次读写文件:stream : 流分为标准输入流(stdin) 和 标准输出流(stdout)   流的特点是数据是有序的,而且必须依次读取,或者依次写入 在Node.js中,流也是一个对象  配合fs 模块使用

所有可以读取数据的流都继承自stream.Readable,所有可以写入的流都继承自stream.Writable   

fs.createReadStream()     获得一个可读取的流   传入两个参数,第一个为文本路径,第二个为编码格式,使用on监听读取事件
               data事件表示流的数据已经可以读取了,end事件表示这个流已经到末尾了,没有数据可以读取了,error事件表示出错
 
var fs = require('fs');


var rs = fs.createReadStream('test.txt','utf-8')   // 打开一个可读取的流

rs.on('data', function(chunk){    //data表示已经在读取,该事件可能触发多次,每次传递的chunk是流的一部分数据。
  console.log('DATA:'+chunk)
})


rs.on('end', function(){
  console.log('读取结束')
})

rs.on('error',function(err){
  console.log('读取错误:'+err)
})
fs.createWriteStream()   获得一个可写入的流, 传入两个参数,第一个为文本路径,第二个为编码格式      该方法复制的数据会替换原本的数据内容
             要以流的形式写入文件,只需要不断调用write()方法,最后以end()结束:
 
 
var fs = require('fs');

var wsl = fs.createWriteStream('test.txt','utf-8')    // 获得一个可写入的流

wsl.write('这是使用流写入的数据');    // 调用write() 方法写入数据,可调用多次
wsl.end();                        // 写入结束 以 end() 方法声明

var ws2 = fs.createWriteStream('test.txt');      // 写入二进制数据
ws2.write(new Buffer('使用流写入二进制数据', 'utf-8'));
ws2.end();

流的赋值:pipe  依次将一个流赋值给另一个流    pipe() 是读取流(Readable)的一个方法    其实就是复制    该方法写入的数据会替换原本的数据内容

var fs = require('fs');

var rs = fs.createReadStream('two.txt','utf-8')      // 获得一个可读取的流

var ws = fs.createWriteStream('test.txt','utf-8')    // 获得一个可写入的流


rs.pipe(ws)   // 将读取流rs的数据复制到写入流ws    ws原本的数据会被替换

默认情况下,当Readable流的数据读取完毕,end事件触发后,将自动关闭Writable流。如果我们不希望自动关闭Writable流,需要传入参数:{end : false}

readable.pipe(writable, { end: false });

 

 

解析前端传递路径:url 模块    通过 url.parse() 将url字符串解析为一个对象

url.parse(url,true)  接收两个参数,当后面为true时,query参数会以对象的形式打印出来
 
url.parse().pathname      解析并获得请求文件地址
'use strict';

var url = require('url');

console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));

结果如下:

Url {
  protocol: 'http:',
  slashes: true,
  auth: 'user:pass',
  host: 'host.com:8080',
  port: '8080',
  hostname: 'host.com',
  hash: '#hash',
  search: '?query=string',
  query: 'query=string',
  pathname: '/path/to/file',
  path: '/path/to/file?query=string',
  href: 'http://user:pass@host.com:8080/path/to/file?query=string#hash' }

构造目录: path 模块   获得当前工作路径并对文件路径进行拼接

path.resolve()     解析当前的路径,传入相对路径参数

path.join()   将各个路径进行拼接    传入各个路径参数

'use strict';

var path = require('path');

var workDir = path.resolve('.'); // 解析当前目录: 输出'/Users/zhengweijie/projects/tests/node'

var filePath = path.join(workDir, 'test.txt');   // 可以有多个参数
// 拼接路径   输出 /Users/zhengweijie/projects/tests/node/test.txt

 

 

服务器:http 模块  

通过http.createServer模块就可以创建node服务器

request对象封装了HTTP请求,  即前端发起的数据请求信息

response对象封装了HTTP响应,即后台需要返回的数据信息
 
可在请求阶段定义各事件:
 
server.on('connection',function(){
  console.log('连接请求中')
})

server.on('data',function(chunk){
  console.log('接收请求中,接收参数chunk')
})

server.on('end',function(chunk){
  console.log('接收请求完成时')
})

server.on('close',function(chunk){
  console.log('接收请求结束时')
})
 
简单的HTTP服务器程序实例:get方式
 
'use strict';

var http = require('http');  // 导入http模块:
// 创建http server,并传入回调函数:  回调函数接收 request 和 response 对象,
var server = http.createServer(function (request, response) { 
     //获得前端HTTP请求的请求方式method和请求地址url:
    console.log(request.method + ': ' + request.url);   
    // 后台进行响应,将HTTP响应200写入response, 同时设置Content-Type: text/html:   响应头
    response.writeHead(200, {'Content-Type': 'text/html'});

     // 将HTTP响应的HTML内容写入response: 即返回的数据内容   响应内容
    response.write('<h1>Hello world!</h1>');

    // 将HTTP响应的HTML内容写入response: 即返回的数据内容   响应尾
    response.end('<h1>end</h1>');
});

// 让服务器监听8080端口:   该端口所有的请求都会被创建的node服务监听到
server.listen(8080);

console.log('Server is running at http://127.0.0.1:8080/');
HTTP服务器程序扩展实例:get方式
 
'use strict'

var http = require('http');  // 引入各个模块
var fs = require('fs');
var url = require('url');
var path = require('path')

var workDir = path.resolve(process.argv[2] ||'.');     // 获得当前的工作目录  

var server = http.createServer(function(request, response){   // 创建HTTP服务
    console.log(request.method+':'+request.url)
    var pathName = url.parse(request.url).pathname           // 获得发起请求的URl路径
    var filePath = path.join(workDir, pathName)              // 将当前目录与请求的路径拼接,得到文件路劲
    console.log(filePath)
    fs.stat(filePath,function(err, stat){     // 使用该文件路径进行查询
        if(!err && stat.isFile()){              
            console.log('200 读取成功'+request.url)
            response.writeHead(200)
            fs.createReadStream(filePath).pipe(response)  // 直接使用流读取文件并赋值给 response 返回前端
        } else {
            console.log('404 文件不存在')
            response.writeHead(404)
            response.end('404 Not Found')
        }
    })
})

server.listen(5858);
console.log('runing now')
 HTTP服务器程序扩展实例:post方式   使用 querystring
 
'use strict';

var http = require('http')
var querystring = require('querystring')


http.createServer(function(req,res){
  var post = ''
  req.on('data',function(chunk){
    post+=chunk
  })

  req.on('end',function(){
    post = querystring.parse(post)
    console.log('参数解析完成,返回name参数')
    res.end(post.name)
  })
}).listen(3000)

http模块提供了两个函数 http.requesthttp.get  , 功能是作为客户端向HTTP服务器 发起请求(类似于ajax)

http.request(options, callback) 发起HTTP请求,需要接收两个参数,option是一个类数组对象,表示请求的参数,callback是请求的回调函数

  callback 传递一个参数,为http.ClientResponse的实例;http.request 返回一个http.ClientRequest的实例

option常用参数:

  host : 请求网站的域名和IP地址

  port : 请求网站的端口,默认是80

  method : 请求方法,默认是get

  path :请求的相对于根的路径,默认是 ‘/’  QueryString应该包含在其中,例如 /search?query=test

  headers : 一个关联数组对象,为请求头的内容

   

例子: (该例子执行报错)

'use strict';

var http = require('http')
var querystring = require('querystring')

// 启动服务
http.createServer(function(req,res){
  var post = ''
  req.on('data',function(chunk){       // 解析post 参数
    post+=chunk
  })

  req.on('end',function(){
    post = querystring.parse(post)
    console.log('参数解析完成,返回name参数')
    res.end(post.name)
  })
}).listen(3000)



var contents = querystring.stringify({   // 声明 contents ,转为字符串
  name:'test',
  age: 21,
  address: 'guangzhou'
});

var options = {     // 声明请求参数
  host: 'localhost',
  path: '/',
  port: 3000,
  method: 'POST',
  headers: {
    'Content-Type':'application/x-www-form-urlecoded',
    'Content-length':contents.length
  }
}
// 客户端发起请求
var req = http.request(options,function(res){
  res.setEncoding('utf-8')            // 声明读取编码,默认是 Buffer
  res.on('data',function(data){
    console.log('后台返回的数据:'+ data)
  })
})

req.write(contents)
req.end()     // 必须调用,表示请求结

http.get 是 http.request的简化版,区别在于http.get自动将请求方法设定为GET方式,同时不需要手动调用 req.end() 结束请求

例子: (该例子执行报错)

var http = require('http')
var url = require('url')
var util = require('util')

// 启动服务
http.createServer(function(req,res){
  console.log('请求到来,开始解析参数')
  var params = url.parse(req.url,true)
  console.log('解析完成')
  console.log(util.inspect(params));
  console.log('向客户端返回')
  res.end(params.query.name)
}).listen(2000)


// 客户端发起请求
http.get({
  host: 'localhost',
  path: '/user?name=test&age=21',
  port: 2000
},function(res){
  res.setEncoding('utf-8')
  res.on('data',function(data){
    console.log('返回的数据为:'+data)
  })
})

http.ClientRequest   该对象是由http.request或http.get返回产生的对象,表示一个已经产生而且正在进行的HTTP请求,它提供了response事件

提供的函数:

  request.abort() 终止正在发送的请求

  request.setTimeout(timeout, callback)   设置请求超时时间,timeout为毫秒数,当请求超时后,触发回调函数

http.ClientResponse   提供三个事件,data 、 end 和close , 分别在数据到达,传输结束和连接结束时触发,其中data事件传递一个参数chunk, 表示接受到的数据
属性:表示请求的结果状态
  statusCode  HTTP状态码。如200, 404 , 500
  httpVersion : HTTP协议版本
  headers : HTTP请求头
  trailers : HTTP请求尾
 
提供的函数:
  response.setEncoding([encoding])    设置读取编码格式,  默认为buffer
  response.pause()     暂停接收数据和发射事件,方便实现下载功能
  response.resume()    从暂停的状态中恢复
  
 

事件模块 events   自定义各种事件

 
 如何自定义一个事件:EventEmitter    
events 模块只提供了一个对象 EventEmitter   ,它的核心是事件的发射和监听(注册)功能的封装。EventEmitter的每个事件注册由一个事件或若干个参数组成。
   EventEmitter支持一次性注册若干个事件,当调用时会依次触发
 
 例子:
 
var EventEmitter = require('events').EventEmitter   // 引入事件模块中的EventEmitter
var event = new EventEmitter();                     // new声明一个EventEmitter 对象 event

event.on('some_event',function(){                 // event.on 注册第一个自定义事件
  console.log('这是第一个自定义事件')
})

event.on('some_event',function(){                 // event.on 注册第二个自定义事件
  console.log('这是第二个自定义的事件')
})

setTimeout(function(){
  event.emit('some_event')           // 使用 emit 调用注册的事件,会依次触发定义的方法
},1000)

 常用的APi:

EventEmitter.on(eventName, function)    注册一个事件,接收事件名称和一个方法作为参数

EventEmitter.emit(eventName, [arg1], [arg2]...)    调用(发射)注册的事件,接收事件名和事件传入参数(可选)作为参数

EventEmitter.once(eventName, function)    类似于EventEmitter.on 注册事件,不过在调用一次后会自动解除,只能调用一次

EventEmitter.removeListener(eventName, funName)    移除注册事件中的某个事件,接收注册的事件名和移除的事件名两个参数

EventEmitter.removeAllListeners(eventName)    移除某个注册事件(整个移除),不传参数的请求下默认删除所有

EventEmitter.once 例子:

var EventEmitter = require('events').EventEmitter   // 引入事件模块中的EventEmitter
var event = new EventEmitter();                     // new声明一个EventEmitter 对象 event


event.once('some_event',function(){
  console.log('这是调用EventEmitter.once的回调')
})  

event.on('some_event',function(name){                 // event.on 注册第一个自定义事件
  console.log('这是第一个自定义事件')
  console.log(name)
})


setTimeout(function(){
  event.emit('some_event')           // 使用 emit 调用注册的事件,会依次触发定义的方法
  event.emit('some_event')          // 再次使用 emit 调用注册的事件,once定义的方法不再触发
},1000)

EventEmitter.removeListener:例子:

var EventEmitter = require('events').EventEmitter   // 引入事件模块中的EventEmitter
var event = new EventEmitter();                     // new声明一个EventEmitter 对象 event


const fun1 = function(){
  console.log('这是第一个自定义事件')
}
const fun2 = function(name){                 // event.on 注册第一个自定义事件
  console.log('这是第二个自定义事件')
  console.log(name)
}

event.on('some_event',fun1)  

event.on('some_event',fun2)

event.removeListener('some_event',fun1)   // 使用removeListener 移除定义的事件

event.emit('some_event')           // 使用 emit 调用注册的事件,会依次触发定义的方法,没有fun2

EventEmitter.removeAllListeners 例子:

var EventEmitter = require('events').EventEmitter   // 引入事件模块中的EventEmitter
var event = new EventEmitter();                     // new声明一个EventEmitter 对象 event


const fun1 = function(){
  console.log('这是第一个注册事件')
}
const fun2 = function(name){            
  console.log('这是第二个注册事件')
  console.log(name)
}

event.on('some_one',fun1)  

event.on('some_two',fun2)

event.removeAllListeners('some_one')   // 使用removeAllListeners 移除注册的事件,不传参数为删除全部

event.emit('some_one')           // 使用 emit 调用注册的事件,不存在事件,已被移除

event.emit('some_two')           // 使用 emit 调用注册的事件

  

 
 
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/zhengweijie/p/7365053.html