Nodejs笔记

nodejs基础知识

nodejs和js的异同

相同点 javascript和nodejs
以ECMAScript为基础 数据结构的定义,语法、内置对象和方法等都相同。

不同点 javascript nodejs
顶层对象 window global
操作对象 操作浏览器,属前端范畴。包括↓
DOM: 操作页面元素的方法;
BOM: 操作浏览器元素的方法。
操作系统/网络等,更偏向于后端。包括↓
OS: 操作操作系统的方法;
file: 操作文件系统的方法;
net: 操作网页的方法;
database: 操作数据库的方法;
net: 操作网页的方法。
模块概念

nodejs的使用

nodejs软件是无界面形式的,打开后类似于命令行,且可以直接在命令行里打开nodejs文件。

操作命令行

  • windows下,通过win+r可以直接打开运行,输入cmd,打开命令行界面
  • 直接敲 node +回车,若得到 >和闪动的光标,表示node安装正确
  • 按2次 ctrl+c可结束执行进程
  • win7在命令行里输入CLS可清屏
  • 命令行里输入node+空格+要运行的程序
  • 命令行内不区分大小写
  • cd回到根目录,cd..回到上级目录
  • 后面输入路径, >后面输入命令

nodejs中的模块

  • 在node中,文件和模块是一一对应的,一个文件就是一个模块
  • 每个模块都有自己的作用域
  • 通过var申明的并不是全局变量,而是该模块作用域下的变量
  • node中要通过 global.变量名 的方式申明全局变量,前面不用加var
  • node中,像全局变量,实际上是当前模块下的变量有:

__filename → 当前文件被解析后的绝对路径,是属性,末尾无括号

模块加载机制

在js中通过<script>标签引入其他js文件,但在node中没有标签的概念,它是用模块加载机制来引入其他文件。即:
require方法 → require('模块地址'); → 使用时要注意两个问题:

  • 一是路径问题:

  1. 地址之间用/,而不是
  2. 既可以写绝对地址,也可以写相对地址
  3. 写相对地址时,若是同一文件夹下的文件,不能省略./
  4. 一旦直接写文件名,会加载node中的核心模块,也就是node_modules中的模块

  • 二是文件查找问题:

查找顺序:文件名→文件名.js→文件名.json→文件名.node→还找不到,报错

module和exports

在node中用var定义的变量是当前模块下的变量,无法直接和外部模块共享,解决办法:

  1. global将变量定义为全局变量;→不推荐这样做
  2. 利用每个模块内置的module对象;
  3. 利用每个模块内置的exports对象;

module对象

module对象保存和提供了与当前模块有关的一些信息,比如,id是当前模块的唯一标识;filename是当前模块的文件名称;children是当前模块加载的其他模块的信息。
module对象中有一个子对象,即exports属性,可以将当前模块中的变量暴露出去;使用方法:module.exports.属性名=变量名;例:

var a=20;
module.exports.a=a;

require方法返回的就是被调用模块的module.exports属性;

exports对象

每个模块中内置的exports对象===该模块下的module.exports属性
一旦改写(不是添加)exports或module.exports,他们就没有指向关系了,所以尽量只是添加,不要改变他们的指向关系

process对象

process是全局对象

stdin/stdout: 标准输入输出流(IO)

stdin和stdout提供了操作输入和输出数据的方法,通常也被称为IO操作

Buffer类

Buffer类用于操作二进制数据流
当为buffer对象分配空间大小后,长度是固定的,不能更改
可以修改长度内的数据,但不能添加数据
length指的是字节长度,不是字符串的长度

  • new Buffer(size);创建一个buffer对象并为这个对象分配一个大小,size为数据类型
var bf = new Buffer(5);
console.log(bf);//<Buffer 88 f3 30 00 02>→打印出来的是16进制数据,数据随机
bf[6]=8;
console.log(bf);//<Buffer 88 f3 30 00 02>→没有出现第6位数
bf[0]="8";
console.log(bf);//<Buffer 08 f3 30 00 02>→第一个数被改写
  • new Buffer(array);创建一个buffer数组
var bf = new Buffer(["ab","2",4]);
console.log(bf);//<Buffer 00 02 04>
bf[6]=8;
console.log(bf);//<Buffer 00 02 04>→同样不能添加数据
bf[0]="8";
console.log(bf);//<Buffer 08 02 04>→同样可以改写数据
  • new Buffer(string,[encoding]);创建一个buffer对象
var bf = new Buffer("hua","utf-8");
console.log(bf);//<Buffer 68 75 61>→16进制
for (var i=0; i<bf.length;i++){
    console.log(bf[i]);//打印出来的是2进制
    console.log(String.fromCharCode(bf[i]));//将编码转换成字符串
}
// 104
// h
// 117
// u
// 97
// a

buffer.write()方法

buffer对象.write(要写入到buffer对象的字符串[,从buffer对象的第几位开始写入][,写入的字符串长度],[写入的字符串的编码]);

buffer.slice()和buffer.copy()方法

相同点:都是截取一个buffer对象,获得一个新的buffer对象
不同点:使用slice,改变新buffer的数据会同时改变原buffer数据;copy就不会

var str="caihua";
var bf=new Buffer(str);
console.log(bf);//<Buffer 63 61 69 68 75 61>
var bf1=new Buffer(5);
console.log(bf1);//<Buffer 00 00 00 00 38>
var bf2=bf.copy(bf1,1,2,3);
console.log(bf1);//<Buffer 00 69 00 00 38>
console.log(bf2);//1,返回的是写入到新bf1的长度

File System文件系统模块

该模块是核心模块,需要使用require方法导入fs模块后使用
该模块提供了操作文件的一些API

fs.open(path,flags,[mode],callback)

path:要打开的文件路径
flags:打开文件的方式,读/写
mode:设置文件的模式,读/写/执行,对应4/2/1
callback:回调函数
  err:文件打开失败的错误提示保存在err里,打开成功err为null
  fd:被打开文件的标识

举个栗子

var projectData={
    "name":"caihua",
    "fileData":[
        {
            "name":"css",
            "type":"dir"
        },{
            "name":"js",
            "type":"dir"
        },{
            "name":"index.html",
            "type":"file",
            "content":"<html>
	<head>
		<title>title</title>
	</head>
	<body>
		<h1>caihua is nice</h1>
	</body>
</html>"
            //
是折行,	是缩进
        }
    ]
};
var fs=require("fs");
if(projectData.name){
    fs.mkdirSync(projectData.name);
    var fileData=projectData.fileData;
    if(fileData && fileData.forEach){//如果fileData存在,并且它是数组,有forEach方法
        fileData.forEach(function(f){//f是数组fileData里的每一个对象
            f.path=projectData.name+"/"+f.name;//构建一个完整的目录
            f.content=f.content||"";//避免没有content时出错
            switch(f.type){
                case "dir":
                    fs.mkdirSync(f.path);
                    break;
                case "file":
                    fs.writeFileSync(f.path,f.content);
                    break;
                default:
                    break;
            }
        })
    }

合并文件,举个栗了

var fs=require("fs");
var filedir="./test";//要合并内容的文件夹
fs.watch(filedir,function(ev,file){//监听要合并内容的文件夹里的内容
    fs.readdir(filedir,function(err,datalist){//读取该文件夹下的内容
        //datalist是一个数组,用来装该文件夹下的文件名
        var arr=[];//用来装要合并内容的文件的路径
        datalist.forEach(function(f){
            if(f){
                var info=fs.statSync(filedir+"/"+f);//参数是路径
                if(info.mode==33206){
                    arr.push(filedir+"/"+f);
                }
            }
        });
        var content="";//用来装该文件夹下每个文件的内容
        arr.forEach(function(f){
            var c=fs.readFileSync(f);
            content+=c.toString()+"
";
        });
        fs.writeFile("./index.js",content);
    })
});

用到的方法:

  1. fs.watch(文件夹所在路径,回调函数)→监听文件夹内的变化
  2. fs.readdir(文件夹所在路径,回调函数)→读取文件夹下所有文件
  3. fs.statSync(文件所在路径)→读取文件详情
  4. fs.readFileSync(文件所在路径)→读取文件内容,得到的是buffer对象,二进制,可以用toString方法转成字符串, 是换行
  5. fs.writeFile(要写入内容的文件的路径,要写入的内容)→写入内容

使用node进行web开发

  1. 用户通过浏览器发送http请求到指定的主机(服务器)
  2. 服务器接收请求,处理请求
  3. 服务器处理完成,返回对应的数据到用户机器(浏览器)
  4. 浏览器接收数据并进行分析和处理

浏览器即客户端,服务器就是服务端,请求过程就是两台机器之间的数据通信,即两台机器的交互过程
要进行web开发,必须搭建一个服务器来接收来自任何客户端的链接和请求,并进行对应的处理
nodejs中可以通过http模块来搭建服务器(非nodejs的核心模块)

http模块

用到的方法

  1. http.createServer(回调函数);→创建并返回一个web服务器对象。
  2. server.listen(port,[hostname,][backlog,][callback])→listen方法可以用来设定监听哪个网卡的哪个端口的数据。
  3. server.address();→{ address: '::', family: 'IPv6', port: 9960 }→获取服务器地址,address不设置,默认监听所有网卡过来的数据;端口可以由node自动分配,每刷新一次,端口会变,所以建议手动设置端口。端口不能随意设置,1-1024之间的端口号已经被约定给系统或应用程序等使用(ipachy监听的端口号是80,ftp监听的端口号是21),所以建议将端口设置大一点
  4. server.on("error",function(err){});→该方法是为了预防端口设置错误,当端口设置错误时触发。
  5. server.on("listening",function(){});→当端口设置正确时触发。
  6. server.on("request",function(){});→当向该地址的该端口发送请求时触发。
    7.http.STATUS_CODES;→是一个对象,全部的标准http响应状态码的集合和简短描述。

端口的概念

网卡是一个数据交互的大通道,如果没有端口,任意程序可以监听网卡上的任意数据,会造成混乱,于是诞生了端口。网络数据交互的程序只能监听从对应端口进入的数据,一个应用程序可以监听多个端口的数据,一个端口的数据只能被一个应用程序监听

request请求

  1. server.on("request",function(){})的request事件其实就是http.createServer(回调函数)里的回调函数,函数有两个参数request和response。request提供了一个客户端信息对象,会存储和客户端发送的请求有关的信息;response则提供了一个服务端信息对象,比如用来处理服务端向客户端发送的数据。
  2. request和response都是http对象的实例

request对象包含的重点内容

  • httpVersion:使用的http版本信息,一般为1.1
  • headers:请求头信息中的数据
  • url:请求的地址
  • method:请求方式

response对象包含的重点内容

  • write(chunk,[encoding]):发送一个数据块到响应正文中。
  • end([chunk,][encoding]):当所有的正文和头信息发送完了后调用该方法告诉服务器,数据已发送完成。这个方法在每次发送完信息后必须调用,且是在最后调用。
  • statusCode:该属性用来设置返回的状态码
  • setHeader(name,value):设置返回头信息
  • writeHead(statusCode,[reasonPhrase],[headers]):这个方法只能在当前请求中使用一次

用户发送http请求→服务器响应并处理数据→返回给客户端→客户端接收数据并进行处理

url模块

url.parse(路径名);→将url解析成一个对象,方便调用

举个栗子

var http=require("http");
var url=require("url");
var server=http.createServer();
server.listen(8080,"localhost");
server.on("request",function(req,res){
    var urlStr=url.parse(req.url);
    switch (urlStr.pathname){
        case "/":
            //首页
            res.writeHead(200,{
                "content-type":"text/html;charset=utf-8"
            });
            res.end("<h1>这是首页</h1>");
            break;
        case "/users":
            //用户页面
            res.writeHead(200,{
                "content-type":"text/html;charset=utf-8"
            });
            res.end("<h1>这是用户页面</h1>");
            break;
        default:
            res.writeHead(404,{
                "content-type":"text/html;charset=utf-8"
            });
            res.end("<h1>这是错误页面</h1>");
            break;
    }
});

使用fs模块实现行为表现分离

用到的方法和属性

  1. __dirname是全局变量。在任何模块文件内部,可以使用__dirname变量获取当前模块文件所在目录的完整绝对路径。
  2. fs.readFile(file,function(err,data){});→读取文件内容
原文地址:https://www.cnblogs.com/giselle527/p/6601030.html