Node入门

背景


最近有一个node服务的项目需要去接手,于是在阅读学习各种有关node的文章,零零总总的看了一些文章,感觉还是一团浆糊,遂整理总结出此文。
此文并未加入自己的理解,主要是从网上查阅资料看到的一些入门教程,将教程中的讲解进行重点知识的记录、梳理。

廖雪峰官网的Node.js

Node.js


在2009年,Ryan正式推出了基于JavaScript语言和V8引擎的开源Web服务器项目,命名为Node.js。虽然名字很土,但是,Node第一次把JavaScript带入到后端服务器开发,加上世界上已经有无数的JavaScript开发人员,所以Node一下子就火了起来。

由于一群开发者对Joyent公司的策略不满(Node幕后一直由Joyent公司资助),于2014年从Node.js项目fork出了io.js项目,决定单独发展,但两者实际上是兼容的。

“分久必合,合久必分”,Joyent公司表示要和解,io.js项目又决定回归Node.js。

将来io.js将首先添加新的特性,如果大家测试用得爽,就把新特性加入Node.js。io.js是“尝鲜版”,而Node.js是线上稳定版,

安装node.js和npm


首先,从Node.js官网下载对应平台的安装程序.
安装完成后,在终端中输出:node -v,显示版本号,说明安装成功。

npm是Node.js的包管理工具(package manager)。
npm已经在Node.js安装的时候顺带装好了。我们在命令提示符或者终端输入npm -v,显示版本号。

第一个Node程序


命令行模式下,输入node回车,进入Node交互式环境。
或者也可以直接node hello.js运行一个.js文件。

模块


在Node环境中,一个.js文件就称之为一个模块(module)。
使用模块可以避免函数名和变量名冲突。这是因为:JavaScript是一种函数式编程语言,它支持闭包。如果我们把一段JavaScript代码用一个函数包装起来,这段代码的所有“全局”变量就变成了函数内部的局部变量。而Node加载一个模块,其实就是对代码进行了一层包装。

要在模块中对外输出变量,用:

1
module.exports = variable;

输出的变量可以是任意对象、函数、数组等等。
要引入其他模块输出的对象,用:

1
var foo = require('other_module');

引入的对象具体是什么,取决于引入模块输出的对象。

关于Node.js的模块原理:
JavaScript语言本身并没有一种模块机制来保证不同模块可以使用相同的变量名。而是因为由于JavaScript是一种函数式编程语言,它支持闭包,Node加载一个js文件,就相当于把代码包装了一下,原来代码中的全局变量变成了函数内部的局部变量,因此每个模块中定义的全局变量并不会相互干扰。

基本模块


Node.js内置的常用模块是为了实现基本的服务器功能,这些模块在浏览器环境中是无法执行的,因为它们的底层代码是用C/C++在Node.js运行环境中实现的。

  • global:相当于浏览器环境中的window。
    在终端中输入node进入node环境,然后输入:for (var k of Object.keys(global)) { console.log(k);},可以查看输出的结果,以更好理解global。
  • process: 是Node.js提供的一个对象,它代表当前Node.js进程。
    如果我们想要在下一次事件响应中执行代码,可以调用process.nextTick().

fs


Node.js内置的fs模块是文件系统模块,负责读写文件。
fs模块同时提供了异步和同步的方法。

异步读取文件

异步读取一个文件的代码如下: fs.readFile('sample.txt','utf-8',function(err, data){})
异步读取时,传入的回调函数接受两个参数,当正常读取时,err参数为null,data参数为读取到的string。当读取发生错误时,err参数代表一个错误对象,data为undefined。
这也是Node.js标准的回调函数:第一个参数代表错误信息,第二个参数代表结果。后面我们会经常用到这种回调函数。

读取二进制文件时,fs.readFile('demo.png',function(err, data){}
不传入文件编码时,回调函数的data返回的是一个Buffer对象。在Node中,Buffer对象就是一个包含零个或任意个字节数的数组(与Array不同)。
Buffer对象转换为String:data.toString('utf-8');
String对象转换为Buffer:Buffer.from(data,'utf-8');

同步读取文件

fs.readFileSync();

写文件

fs.writeFile('output.txt',data, function(err){};
writeFile()的参数依次为文件名、数据和回调函数。
和readFileSync()类似,写入文件也有一个同步方法:writeFileSync();

stat

如果我们要获取文件大小、创建时间等信息,可以使用fs.stat()方法,此方法返回一个stat对象,能告诉我们目录文件详细信息。
是否是文件:stat.isFile();
是否是目录:stat.isDirectory();
若是文件,文件大小: stat.size;
若是文件,文件创建时间:stat.birthtime;
若是文件,文件修改时间:stat.mtime;

stat()也有一个对应的同步方法:statSync();

stream


stream是Node.js提供的又一个仅在服务端可用的模块,目的是支持“流”这种数据结构。
流分为:stain(标准输入流)、staout(标准输出流)。

读取文件流的核心语法是: fs.createReadStream(),代码见:文件读取文本

以流的形式写入文件,只有不断调用write()方法,代码见:文本写入文件

将Readable流和Writable流串起来,所有的数据从Readable流进入Writable流,这种操作叫做pipe。在Node.js中,Readable流有一个pipe()方法,就是用来干这件事的。代码见:pipe

http


要开发HTTP服务器程序,从头处理TCP连接,解析HTTP是不现实的。这些工作实际上已经由Node.js自带的http模块完成了。应用程序并不直接和HTTP协议打交道,而是操作http模块提供的request和response对象。

request对象封装了HTTP请求,我们调用request对象的属性和方法就可以拿到所有HTTP请求的信息;

response对象封装了HTTP响应,我们操作response对象的方法,就可以把HTTP响应返回给浏览器。

crypto


crypto模块的目的是为了提供通用的加密和哈希算法。用纯JavaScript代码实现这些功能不是不可能,但速度会非常慢。Nodejs用C/C++实现这些算法后,通过crypto这个模块暴露为JavaScript接口,这样用起来方便,速度也快。

  • MD5和SHA1是常用的哈希算法,用于给任意数据一个“签名”,这个签名通常用一个十六进制的字符串表示。
  • Hmac算法:也是一种哈希算法,不同的是,它还需要加一个密钥。
  • AES算法:是一种常用的对称加密算法,加解密都用同一个密钥。
  • Diffie-Hellman:DH算法是一种密钥交换协议。
  • RAS:RAS算法是一种对称加密算法
liugezhou wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
Enjoy Yourself EveryDay!