06月21, 2016

node学习笔记(1)

node学习笔记第一篇。

1. createSever

node可以通过http.createSever来创建一个http服务器。

var server = http.createServer(function(request, response){});

它接收一个函数,函数中有两个形参,request和response。每次URL发生变化时,都会进入该函数。

request.method
request.url (这里的URL是指当我请求这个页面的所有地址,包括js、image、css,路径是以"/"开头的)

这里可以思考一个问题,怎么屏蔽掉/favicon.ico这个URL?

response.statusCode = 200;//设置状态码
//设置响应的类型,编码为utf-8
response.setHeader("Content-Type","text/html;charset=utf-8");
response.setHeader("name","zpu");//设置响应头
response.write("数据");
response.end();

上面的响应类型,现在是写死了,但有时候这个类型可能需要动态获取,可以通过mime这个npm模块来得到

var mime = require("mime");

mime.lookup("/path/to/file.txt");         // => "text/plain" 
mime.lookup("file.txt");                  // => "text/plain" 
mime.lookup(".TXT");                      // => "text/plain" 
mime.lookup("htm");                       // => "text/html"

2. global

  • 全局捕获错误

在实际编码过程中,我们容易忘记对某行或者某几行代码(容易出错的)进行try catch,那么可以通过以下的方式,来进行全局的错误捕获。

process.on("uncaughtException",function(e){
    console.log("uncaughtException", e.message);
});
  • process的输入输出

输出的代码为:

process.stdout.write("hello");

它是console.log的实现。

输入的代码为:

process.stdin.on("data",function(data){
 console.log(data.toString());
});

输入一些文字,回车即可看到效果,回调函数中的data,默认为buffer对象,只有当调用toString方法时,才会转为字符串。

  • process.argv

获取命令行的参数,通常我们自己加的,是从第2个开始截取的,譬如:

node test.js --help

要得到--help,只能通过process.argv的第2个下标索引。

  • process.cwd()

获取当前工作目录,除此之外还可以使用__dirname

  • nextTick、setImmediate

理解nodejs里的process.nextTick()

初探传说中的setImmediate函数

时间顺序:nextTick> setTimeout>setImmediate>异步IO

  • util

工具类,里面包含了很多好用的方法,如:

isArray
isDate
isRegExp

甚至可以做来做继承

var util = require("util");
function Parent(){
    this.name = "Parent";
    this.age = 6;
    this.say = function(){
        console.log("hello",this.name);
    }
}
Parent.prototype.showName = function(){
    console.log(this.name);
}

function Child(){
    this.name = "Child";
}
//不能传参 会继承私有属性
//Child.prototype = new Parent(); //Parent.prototype
//Child.prototype = Object.create(Parent.prototype);
util.inherits(Child,Parent);

var child = new Child();
//console.log();
child.showName();

注意:,上面的写法只是将Person的prototype给了child,并没有把实例继承给Child。

util.inspect可以用来调试和错误输出,具体写法为:

function Person(){
    this.name = "zfpx";
    this.parent = {
        name:"parent"
    }
}
Person.prototype.toString = function(){
    console.log("this is ",this.name);
}

var p = new Person();
p.toString();
/**
 * showHidden 是否显示隐藏属性
 * depth 对象的递归显示深度
 * colors 是否显示 颜色
 */
console.log(util.inspect(p,true,null,true));

3.events

让对象拥有events的方法,比如on、once、emit这些,简单示例:

var EventEmitter = require("events");
var util = require("util");
function Person(name){
    this.name = name;
}
util.inherits(Person,EventEmitter);

4.module

  • require.cache

模块会在第一次加载后缓存,我们可以通过它来查看缓存的对象。

我在stackoverflow上面看到一个问题:node.js require() cache - possible to invalidate?,下面有一个回答:

You can always safely delete an entry in require.cache without a problem, even when there are circular dependencies. Because when you delete, you just delete a reference to the cached module object, not the module object itself, the module object will not be GCed because in case of circular dependencies, there is still a object referencing this module object.

可以用它来解决循环依赖的问题。

同时也可以用来清理缓存。

// require是可以直接载入JSON文件的,但是载入完后记得删除它的缓存
var data = require(filename); 
delete require.cache[filename];
  • module.loaded、module.children、module.parent

分别表示是否load,module的子模块、module的父模块

5.buffer

Buffer对象是Node.js用来处理二进制数据的一个接口。JavaScript比较擅长处理Unicode数据,对于处理二进制格式的数据(比如TCP数据流),就不太擅长。Buffer对象就是为了解决这个问题而提供的。该对象也是一个构造函数,它的实例代表了V8引擎分配的一段内存,基本上是一个数组,成员都为整数值。

var buff = new Buffer("hello");
console.log(buff); //<Buffer 68 65 6c 6c 6f>
console.log(buff[0]); //104,即它调用了toString()方法,将0x68转为十进制

toString()方法可以接收参数,譬如2、16、32等,表示将数字转为二进制、十六进制、三十二进制等。

在buffer里面存的是十六进制(0x68,类似这样的)。因为我不是计算机专业出身,所以就百度查了一下“为什么内存地址要用16进制”,回答是:在计算机内部,二进制数据转换为十六进制数据最直接、最快捷,占用存储空间最小。

将十六进制转回字符,可以使用:

String.fromCharCode(0x68) // h

buffer的适用场景一般是来处理一些二进制数据(比如读取文件数据,http请求中的post传递的数据等)。

在网上看到一篇文章: node的 Buffer 介绍-lovenyf-ChinaUnix博客 ,写的挺赞的。

手动实现一个concat方法,实现拼接多个buffer对象:

function concat(arrBuffers, length){
    if(arrBuffers.length==1)
       return arrBuffers[0];
    if(length == undefined){
        length = 0;
        arrBuffers.forEach(function(buf){
            length +=buf.length;
        });
    }

    var buffer = new Buffer(length);
    var curIndex = 0;
    arrBuffers.forEach(function(buf){
        buf.copy(buffer,curIndex);
        curIndex+=buf.length;
    });
    return buffer.slice(0,curIndex);
}

var buffer1 = new Buffer("张三");
var buffer2 = new Buffer("吃饭");

var buffer3 = concat([buffer1, buffer2], 100);
console.log(buffer3.toString());

6.file

  • readFile/readFileSync:读取内容到缓存区

API

其实最好的学习莫过于是看官网的API,确实不要太详细

建议将node升级到6.X版本

  • writeFile/writeFileSync:写入内容到指定文件

  • appendFile/appendFileSync:添加文本到文件的后面

关于base64编解码,可以参考这篇文章

  • read/readSync:读取文件中的部分内部
fs.readSync(fd, buffer, offset, length, position)

fd为Interger,当调用fs.openSync时,返回对象即为fd(Returns an integer representing the file descriptor.

举个例子:

var fd = fs.openSync("line.txt", "r");
var buffer = new Buffer(3);
/**
 * fd 文件描述符
 * buffer 存放数据的容器
 * offset 往buffer里写的偏移量
 * length 长度
 * position 文件的当前读取位置
 */
fs.readSync(fd, buffer, 0, 3,0);

在读取的时候,文件会以流的形式,进行输出的截取,这里是表示从第1位开始,取长度为3。注意这个结果有可能是为乱码。

read实现读取文件的功能

var fs = require("fs");
var list = [];

fs.open("line.txt","r",function(err,fd){
    var pos =0;
    function read(){
        var buffer = new Buffer(3);
        fs.read(fd,buffer,0,3,pos,function(err,bytesRead){
            list.push(buffer.slice(0,bytesRead));
            pos += bytesRead;
            if(bytesRead>0)
                read();
            else{
                var result = Buffer.concat(list);
                console.log(result.toString());
            }
        });
    }
    read();
});
  • write/writeSync:将缓存区的部分内容写入文件

  • fs实现console

write/read的第一个参数为fd,当fd可以为fs.open出来的对象,也可以是固定值,比如0,1,2

/**
 * 0 stdin
 * 1 stdout
 * 2 stderr
 */
var fs = require("fs");
fs.write(2,"珠峰培训",function(err){})

个人感觉buffer流那一块的操作(有时候需要的只是读取/输出部分内容,因此需要read/write),确实比较复杂,目前在实际工作中(譬如写工具)的操作文件还是比较容易的。

相比与fs,我个人更倾向于使用fs-extra

本文链接:www.my-fe.pub/post/node-study-part1.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。