nodejs学习笔记
命令行
cmd的一些操作:
1、dir:列出当前目录下所有文件
2、cd:进入到指定目录
3、.:表示当前目录
4、…:表示上一级目录
5、md:新建一个文件夹
6、rd:删除一个文件夹
环境变量:
当我们在命令行窗口打开一个文件,或调用一个程序时,系统会首先在当前目录下寻找文件程序,如果找到了则直接打开,如果没有找到则会依次到环境变量path的路径中去找,直到找到为止,如果没找到就报错。
所以我们可以将一些经常需要访问的程序和文件的路径添加到path中,这样我们就可以在任意位置来访问这些文件和程序。
进程和线程
进程:进程负责为程序的运行提供必备的环境。进程相当于工厂中的车间。
线程:线程计算机中的最小计算单位,线程负责执行进程中的程序。线程相当于工厂中的工人。分为单线程和多线程。
单线程:JS是单线程!!!
nodejs
什么是nodejs?
Node.js是一个能够在服务器端运行Javascript的开放源代码、跨平台Javascript运行环境。
Node采用Google开发的V8引擎运行js代码,使用事件驱动、非阻塞和异步I/O模型等技术来提高性能,可优化应用程序的传输量和规模
node用途:
1、Web服务API,比如REST;
2、实时多人游戏
3、后端的Web服务,例如跨域、服务器端的请求
4、基于Web的应用
5、多客户端的通信,如即时通信
node的服务器是单线程的,Node处理请求时是单线程,但是在后台拥有一个I/O线程池。
模块化
在node中,一个js文件就是一个模块。每一个js文件中的js代码都是独立运行在一个函数中的,而不是全局作用域,所以一个模块中的变量和函数在其他模块中无法访问。
如何解决:
可以通过exports来向外部暴露变量和方法。只需要将需要暴露给外部的变量和方法设置为exports的属性即可。
如何引入外部模块:
在node中,使用require()函数来引入外部的模块,require()可以传递一个文件的路径作为参数,node将会自动根据该路径来引入外部模块。使用require()引入模块后,该函数会返回一个对象,这个对象代表的是引入的模块。
模块标识
使用require()引入外部模块时,使用的是模块标识,可以通过模块标识来找到指定的模块。
模块分为两类:核心模块和文件模块。
核心模块:由node引擎提供的模块,核心模块的标识就是模块的名字。
文件模块:由用户自己创建的模块,文件模块的标识就是文件路径。
在node中有一个全局对象global,它的作用和网页中window类似。
在全局中创建的变量都会作为global的属性保存;在全局中创建的函数都会作为global的方法保存。
实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递了5个实参:
exports:该对象用来将变量或函数暴露到外部
require:函数,用来引入外部的模块
module:代表当前模块本身,exports就是module的属性。
_filename:当前模块的完整路径。
_dirname:当前模块所在文件夹的路径
模块暴露
module.exports 和 exports 的区别:
通过exports只能使用.的方式来向外暴露内部变量。exports.xxx=xxx;
而module.exports 既可以通过.的形式,也可以直接赋值:module.exports.xxx=xxx ; module.exports={ };
包
包(package):包是由包结构和包描述文件两个部分组成。
包结构:用于组织包中的各种文件。
包实际上就是一个压缩文件,解压以后还原为目录。符合规范的目录,应该包含如下文件:
1、package.json 描述文件
2、bin 可执行二进制文件
3、lib js代码
4、doc 文档
5、test 单元测试
包描述文件:描述包的相关信息,以供外部读取分析。
包描述文件用于表达非代码相关的信息,他是一个JSON格式的文件-package.json,位于包的根目录下,是包的重要组成部分。一些重要的字段:name、description、version、keywords等
npm
npm(Node Package Manager):对于Node而言,NPM帮助其完成了第三方模块的发布、安装和依赖等。借助NPM,Node与第三方模块之间形成了很好的生态系统。
npm的一些命令:
npm -v:查看版本
npm :帮助说明
npm search 包名:搜索包
npm install/i 包名:下载包
npm remove/r 包名:删除包
npm install 包名 --save:安装包并添加到依赖中
npm install:下载当前项目所依赖的包
npm install 包名 -g:全局安装包(全局安装的包一般都是一些工具)
node搜索包的流程:
node在使用模块名字来引入模块时,它会首先在当前目录的node_modules中寻找是否含有该模块。如果有则直接使用,如果没有则去上一级目录的node_modules中寻找。一直找到磁盘的根目录,如果依然没有就会报错
Buffer缓冲区
Buffer缓冲区:Buffer结构和数组很像,操作的方法也和数组类似。数组中不能存储二进制文件,而Buffer就是专门用来存储二进制文件的数组。使用Buffer不需要引入外部模块,直接使用即可。
在Buffer中存储的都是二进制数据,但是在显示时都是以十六进制的形式显示。Buffer中每一个元素的范围是从00 - ff,Buffer中的一个元素,占用内存的一个字节。
创建Buffer:
var buf= Buffer.alloc(10);//创建一个10个字节的Buffer
在Buffer中操作元素:
buf[0]=88; //在Buffer的0位置上添加元素88
Buffer的大小一旦确定,则不能修改,Buffer实际上是对底层内存的直接操作。
只要数字在控制台或页面中输出一定是十进制!
Buffer.allocUnsafe(size):创建一个指定大小的Buffer,但是Buffer中可能含有敏感数据。
Buffer.from(str):将一个字符串转换为buffer。
Buffer.toString():将缓冲区的数据转换成字符串。
文件系统
文件系统(fs):文件系统通过Node来操作系统的文件。
使用文件系统,需要首先引入fs模块,fs是核心模块,直接引入不需要下载。
同步和异步调用:
fs模块中所有的操作都有两种形式可供选择同步和异步。
同步文件系统会阻塞程序的执行,也就是除非操作完毕,否则不会向下执行代码。
异步文件系统不会阻塞程序的执行,而是在操作完成时,通过回调函数将结果返回。
同步文件的写入
步骤:
1、打开文件:
fs.openSync(path,flags[,mode])
path:要打开文件的路径
flags:打开文件要做的操作类型
例如:‘r’表示只读,‘w’表示可写;
mode:设置文件的操作权限,一般不传
返回值:该方法会返回一个文件的描述符作为结果,可以通过该描述符对文件进行各种操作。
2、向文件写入内容:
fs.writeSync(fd,string[,position[,encoding]])
fd:文件描述符
string :要写入的内容
position:写入的起始位置
encoding:写入的编码,默认utf-8;
3、保存并关闭文件
fs.closeSync(fd)
fd:要关闭文件的描述符
异步文件的写入
步骤:
1、打开文件:
fs.open(path,flags[,mode],callback)
path:要打开文件的路径
flags:打开文件要做的操作类型
例如:‘r’表示只读,‘w’表示可写;
mode:设置文件的操作权限,一般不传
callback:回调函数;其中两个参数为:err和描述符fd
该方法不返回描述符,异步调用的方法都是通过回调函数返回的!
2、向异步文件写入内容:
fs.write(fd,string[,position[,encoding]],callback)
fd:文件描述符
string :要写入的内容
position:写入的起始位置
encoding:写入的编码,默认utf-8;
callback:回调函数
3、保存并关闭文件
fs.close(fd,callback)
简单文件的写入
fs.writeFile(file,data[,options],callback) //异步
fs.writeFileSync(file,data[,options]) //同步
file:要操作的文件的路径
data:要写入的数据
options:选项 可以对写入进行一些设置
callback:当写入完成后执行的函数
流式文件写入
同步、异步和简单文件的写入都不适合大文件的写入,性能较差,容易导致内存溢出。
步骤:
1、创建一个可写流:
fs.createWriteStream(path[,options]);
可以用来创建一个可写流
path:文件路径
options:配置的参数
var ws=fs.createWriteStream("hello.text");
//通过ws向文件输入内容
ws.write("我是hello中的内容,我正在写入")
2、可以通过监听流的open和close事件来监听流的打开和关闭
on(事件字符串,回调函数):可以为对象绑定一个事件
once(事件字符串,回调函数):可以为对象绑定一次性事件。该事件会在触发一次后自动失效。
end():关闭流。
文件读取
简单文件的读取
fs.readFile(path,[,options],callback) //异步
fs.readFileSync(path,[,options]) //同步
path:要读取的文件的路径
options:读取的选项
callback:回调函数,通过回调函数将读取到的内容返回(err,data)
err错误对象;data:读取到的数据,会返回一个Buffer
流式文件的读取
流式文件读取也适用于一些比较大的文件,可以分多次将文件读取到内存中。
1、创建一个可读流:
var rs=fs.createReadStream("");
2、如果要读取一个可读流中的数据,必须要为可读流绑定一个data事件,data事件绑定完毕,他会自动开始读取数据。
3、pipe():可以将可读流中的内容,直接输出到可写流中