1、node.js介绍
诞生于2009年,它不是一门语言也不是一门框架,它是基于Google V8引擎的JavaScript运行时环境,同时结合Libuv拓展了JavaScript功能,使之支持IO,fs等语言才有的特性,使得JavaScript能够同时具有DOM操作(浏览器)和I/O,文件读写、操作数据库等能力。
应用:淘宝双十一、去哪儿网PC端核心业务;前端工具 VScode、webpack等具有Node.js开发
node的包管理工具npm成为世界中开源包管理中最大的生态、功能强大。
2、特点
- 事件驱动
- 非阻塞IO模型(异步)
- 轻量和高效
3.、在一线企业中的应用
①作为中间层
②做一些小型网站的后端
- 减少客户端内存,不会像MVVM模式的项目把页面渲染和数据请求都压在客户端,而是在服务端完成
- SEO性好,不像mvvm模式页面由js生成,而是在服务端渲染好html字符,有利于网页被搜索到
- 前端可以操控的范围增多,甚至可以操作服务器,数据层面的优化,比如中间层使用nginx、redis来优化项目,应对高并发。
优点:中间层模式是一种开发模式上的进步,但这种好的模式成本过高,如果没有一定量级的项目没必要使用
4、node.js中的module.exports和exports
- Node中每个模块都有一个module对象,module对象中有一个exports属性作为借口对象,我们需要把模块之间公共方法或属性挂载到这个接口对象中,方便其他的模块使用 这些公共的方法或属性。
- Node中每个模块的最后,都会return module.exports, 默认module.exports = {}
- Node中每个模块都会把module.exports指向的对象赋值给一个变量exports,即module.exports == exports
- module.exports == XX,表示当前模块导出一个单一成员,require导入的就是一个{ ... }
- 如果需要导出多个成员,必须使用module.exports.xxx = xxx。
5、node、js中require加载第三方包的规则
- 找写require文件同级目录中的node_module下面的同名文件,同级目录中没有node_module,就找父级(父级、祖父级等)的node_module
- 找该文件夹下面package.json中的main,这个main属性值就是你引入的文件路径
6、npm 常见命令
npm 全名为node package manager,我们平时开发项目都需要使用npm命令安装依赖
7、文件读取(同步读取)
- 使用fs.readFileSync()读取文件,第一个参数为文件名或文件描述符,第二个参数是一个对象,该对象有两个属性,一个是encoding,一个是flag(是读取文件--“r”,还是文件写入--“w”,还是追加--“a”)。官方文档该方法描述如下:
- 读取文件写法如下
const fs = require("fs");
const content = fs.readFileSync("txt.txt", {flag: 'r'});
console.log(content.toString());
或者(指定encoding的编码格式需要与读取文件的编码格式一致,因为此例中的txt.txt文件格式是utf-8,所以我们指定utf-8之后可直接输出)
const fs = require("fs");
const content = fs.readFileSync("txt.txt", {flag: 'r', encoding: "utf-8"});
console.log(content);
- 输出的结果如下
PS C:\Users\tcsc6\Desktop\node_1> node .\index.js
这是一个txt.txt
总结:readFileSync读取文件中如果不设置encoding编码方式,直接输出是一耳光Buffer缓冲区,需要使用toString转换成字符串进行展示或者是操作;如果在readFileSync中设置encoding编码方式,使不使用toString都会输出字符串。
8、文件读取(异步读取)
- 使用fs.readFile()读取文件,第一个参数为文件名或文件描述符(必传);第二个参数是一个对象(可传可不传)该对象有两个属性,一个是encoding,一个是flag(是读取文件--“r”,还是文件写入--“w”,还是追加--“a”),如果不传,默认encoding为“utf-8”,默认flag为“r”,;第三个参数callback(必传),官方文档该方法描述如下:
- 该方法读取如下:
const fs = require("fs");
fs.readFile('txt.txt', (err, data) => {
if(err) {
console.log(err);
} else {
console.log(data);
}
console.log("我证明javascript是单行执行!")
});
console.log("我证明他是异步!");
- 输出结果为
PS C:\Users\tcsc6\Desktop\node_1> node .\index.js
我证明他是异步!
<Buffer e8 bf 99 e6 98 af e4 b8 80 e4 b8 aa 74 78 74 2e 74 78 74 20 20>
我证明javascript是单行执行!
总结:如果不指定编码方式默认输出为Buffer缓冲器,readFile是异步函数,javascript是单行执行。
- 要输出utf-8格式的文本需要指定encoding为utf-8
const fs = require("fs");
fs.readFile('txt.txt', {encoding: "utf-8"}, (err, data) => {
if(err) {
console.log(err);
} else {
console.log(data);
}
console.log("我证明javascript是单行执行!")
});
console.log("我证明他是异步!");
- 输出结果为正常的字符串
PS C:\Users\tcsc6\Desktop\node_1> node .\index.js
我证明他是异步!
这是一个txt.txt
我证明javascript是单行执行!
- 封装异步读取文件Promise
function readFileAsync(url) {
return new Promise( (resolve, rejects) => {
fs.readFile(url, {encoding: 'utf-8', flag: 'r'}, (err, data) => {
if(!err){
resolve(data);
} else {
rejects(err)
}
})
})
}
readFileAsync("txt.txt").then( res => {
console.log(res);
})
9、文件写入(跟文件读取一样,分异步和同步方法,因同步一般不会使用,下面只介绍异步方法)
-
writeFile文件写入,第一个参数是文件名称(必填),第二个参数为写入的数据(必填),第三个参数是编码方式和操作类型(flag :append --> a 追加 ;write --> w 文件写入),该参数是可选填,第四个参数是错误回调函数,官方此方法介绍如下图:
- 实例操作:封装一个写入文件(追加方式)的promise函数(使用async 和 await)
const fs = require("fs");
const { resolve } = require("path");
const { rejects } = require("assert");
function writefs(url, data, flag = "a") {
return new Promise((resolve, rejects) => {
fs.writeFile(url, data, {encoding: "utf-8", flag}, err => {
if(!err){
resolve("写入成功!");
} else {
rejects(err);
}
})
})
}
async function writeFileAsync() {
let connect = await writefs("txt.txt", "吃饺子\n");
console.log(connect);
let connect1 = await writefs("txt.txt", "红烧狮子头\n");
console.log(connect1);
let connect2 = await writefs("txt.txt", "水饺\n");
console.log(connect2);
}
writeFileAsync()
- 输出
PS C:\Users\tcsc6\Desktop\node_1> node .\index.js
写入成功!
写入成功!
写入成功!
10、删除文件,同样只介绍异步删除文件 fs.unlink(path, callback)
- 使用fs.unlink(path,callback),第一个参数是文件路径,第二个参数是回调函数(只有err)
- 代码实例
const fs = require("fs");
fs.unlink("txt222.txt", () => {
console.log("删除成功!");
})
- 执行结果:
11、Buffer缓冲器(安全的alloc)
- 解决的问题
- 数组不能进行二进制数据的操作
- 因为js数组一般不指定长度,数组地址存放在heap中,存放的地方也不连续,引用的时候效率就会降低,导致js数组不想Java、python等语言效率高
- buffer内存空间开辟出固定大小的内存,存放的是连续的引用的时候很容易找到,效率高
- 官网方法
- 实例及输出
const buf = Buffer.alloc(10);
buf[0] = "123";
buf[1] = "255";
console.log(buf);
console.log(buf.toString());
console.log(buf[0]);
console.log(buf[0].toString());
总结:Buffer.alloc(10)开辟10个字节的数组,数组的每一项都可以进行赋值,之后我们可以通过获取数组项的方法获取某一项;
12、同样的还有allocUnsafe,不安全Buffer缓冲器
- 官网方法介绍
- 实例
const unsafebuf = Buffer.allocUnsafe(10);
unsafebuf[0] = "123";
console.log(unsafebuf);
console.log(unsafebuf[0].toString() + "\n");
总结:Buffer.allocUnsafe()同样也可以通过传入数字进行给Buffer设置长度,获取的时候使用[0、、]方式获取。
13、读取文件目录(fs.readdir() )这里只介绍异步