Node.js(2)


前言

nodejs主要是做web服务端
nodejs内置了很多的包,需要不同的功能可以引入对应的包

一、创建简单的服务器

// 1. 创建一个简单的web服务器,引入网络模块
const http = require("http");
// 2. createServer创建一个web服务器,并传入回调函数
http.createServer(function (request, response) {
    // request是请求对象,客户端发送请求携带的信息放入该对象
    // response 是服务端的响应对象,服务器相关的操作都是在该对象
    // writeHead 设置服务端响应头,200是status状态码,content-type是服务端返回的数据类型是文本类型,charset=UTF-8解决输出中文乱码
    response.writeHead(200, { "content-type": "text/plain";charset=UTF-8' });
    // end方法向客户端发送数据
    response.end("hello node.js");
  }).listen(8080);
console.log("server start ok");

二、文件模块

1. fs 模块

文件操作有同步和异步版本,推荐用异步版本

1.读文件 readFile

同步模式中,先去读文件,读完后才会执行后面的代码。
异步模式中,先执行fs.readFile()函数立刻执行后面的代码,fs.readFile()函数会去读里面的文件,成功后执行。

// 引入fs文件模块,fs模块可以操作系统中的各种文件
const fs = require("fs")

// 1. 同步模式(阻塞模式),前面的代码执行完成后才能执行后面的代码
// 同步方式读取hello02.text文件内容
const txt = fs.readFileSync("hello.txt")
// 读取内容以流方式展示,需要转为字符串
console.log(txt.toString());
console.log("文件读取中");
// 结果:Hello text!  文件读取中


//2. 异步方式(非阻塞模式),前面代码不影响后面代码执行,同时执行
fs.readFile("hello.txt",(err,data)=>{
    if(!err){
        console.log(data.toString());
    }
})
console.log("文件读取中");
// 结果:文件读取中  Hello text!   

2. 查看文件信息 stat

stat(path,callback(err,status))

const fs = require("fs");
fs.stat(__dirname + "/assets/a1.txt", function (err, status) {
  if (!err) {
    console.log(status);
  }
});

3. 原始打开读取关闭文件

open(path,flag[,mode],callback(err,fd))
path文件路径
flag打开文件的模式
mode文件权限(默认是0666[可读可写])

const fs = require("fs")

fs.open("txt1.txt","r",(err,fd)=>{
    if(err){
        console.log(err.message);
    } else{
        // 打开文件返回的fd并不是文件内容,只是文件打开的一个状态
        // console.log(fd); // 3

        // 打开文件以后需要用read方法,读取文件内容并存入缓存区
        // read(fd,buffer,offset,length,position,callback(err,bytes))
        let buf = new Buffer.alloc(1024)
        fs.read(fd,buf,0,buf.length,0,(err,length)=>{
            if(err){
                console.log(err.message);
            } else {
                console.log("读取了:"+ length +"读取内容:"+ buf.toString());
            }
            // 读取完文件后需要关闭文件,释放内存
            fs.close(fd,(err)=>{
                if(err){
                    console.log(err.message);
                    return
                }
                console.log("文件已关闭");
            })
        })
    }
})

4. node封装 打开读取关闭文件

读取文件 readFile

readFilereadFile(path,callback(err,data)) 读取文件操作的方法,内部封装了打开,读取,关闭的操作。

const fs = require("fs")
fs.readFile("text.txt",(err,data)=>{
    if(err){
        console.log(err.message);
        return
    }
    console.log(data.toString());
})
写入文件 writeFile

写入文件的方法,没有文件则创建文件,有则覆盖

const fs = require("fs")
fs.writeFile("txt1.txt","覆盖的文本txt",(err)=>{
    if(err){
        console.log(err.message);
    }
    console.log("写入成功");
})
删除文件 unlink
const fs = require("fs")
fs.unlink("txt1.txt",(err)=>{
    if(err){
        console.log(err.message);
    }
    console.log("删除成功");
})

5. 目录的创建读取删除

创建目录 mkdir
const fs = require("fs")
fs.mkdir("static",(err)=>{
    if (err) {
        console.log(err.message);
        return;
    }
    console.log("创建成功");
})
删除目录 rmdir
const fs = require("fs")
fs.rmdir("static",(err)=>{
    if (err) {
        console.log(err.message);
        return;
    }
    console.log("创建成功");
})
读取目录 readdir

读取目录下的所有文件,需要使用递归方式,判断目录下面如果还有目录,接着往下读。
isDirectory() 判断是否是一个目录

const fs = require("fs")

fs.readdir("assets",(err,files)=>{
    if (err) {
        console.log(err.message);
        return;
      }
    // 返回的是文件对象数组
    console.log(files);
})

// 读取目录下的所有文件
function readAllDir(path){
    // 传入path路径,判断是一个文件还是目录
    fs.stat(path,(err,status)=>{
        if (err) {
            console.log(err.message);
            return;
        }
        // 判断如果是一个目录,则直接读取目录
        if(status.isDirectory()){
            fs.readdir(path,(err,files)=>{
                if (err) {
                    console.log(err.message);
                    return;
                }
                files.forEach((item)=>{
                    readAllDir(path + "/" + item)
                })
            })
        } else { // 是文件
            console.log("文件名:" + path);
        }
    })
}
readAllDir("assets")

2. events 事件循环系统监听

nodejs 是单进程单线程,但是v8引擎提供了异步执行的回调接口,所以nodejs可以同时处理大量的并发请求,性能非常高
nodejs 所有事件的机制都是使用的观察者模式(事件驱动程序)。
在事件驱动程序中,会有一个事件循环系统监听事件,当检测到事件执行,触发对应的回调函数。

// 引入events 模块(nodejs的事件都是基于events模块封装的)
const events = require("events");

// 1. 创建事件触发器(eventEmitter)对象
let eventEmiter = new events.EventEmitter();
// 2. 创建消费者(监听者),监听事件的执行,并触发对应的回调函数
// 监听connect事件,如果触发connect事件,则执行对应的回调函数
// on监听的事件则会进入事件循环系统,监听connect事件
eventEmiter.on("connect", function (data) {
  console.log("事件执行", data);
});
//3. 触发connect事件,并向回调函数传递参数
setTimeout(function () {
  eventEmiter.emit("connect", { name: "zhang" });
}, 2000);

3. buffer 缓冲区

Buffer类可以创建一个存放二进制数据的缓存区,可以存储比较原始的数据类型

// 1. Buffer.from(string, encode) 返回一个string初始值的buffer实例
// string是buffer的存储数据,encode是存储数据编码格式(默认是utf-8,可以省略)
let buff = Buffer.from("hello 中国");
// 默认buff显示用16进制,需要用toString转为字符串。
console.log(buff.toString());

// 2. alloc(size[,fill[,encode])
//  返回一个指定大小(存储字节数量固定)的buffer实例,size是字节数,fill是存储的内容,encode编码方式
// 超过的字节不会存储成功
let buf1 = Buffer.alloc(6, "xxxxxxxx");

// 3. write(string,[offset,[length,encode]])
// 向buffer缓存区重新填写内容,超过的长度会被丢弃
// string写入的内容,offset是开始的位置索引(默认从0),length是写入的长度(默认是buffer的长度)
let len = buf1.write("chinese", 3, 2);
console.log(buf1.toString());

// 4. 合并缓存区
const bufa = Buffer.from("html");
const bufb = Buffer.from("javascript");
const bufc = Buffer.concat([bufa, bufb]); // concat合并多个buffer并返回一个新的
console.log(bufc.toString());

4. stream 流

是数据的传输,是有序的,有方向的数据传输(对buffer的一种封装)
stream 流对象是EventEmitter对象的一个实例,stream一般是用于大量数据的传输
strea流是fs模块里面的api
有四种流:

  1. 可读流Readable
  2. 可写流Writable
  3. 可读写流Duplex
  4. Transform 可读写过程中还可以修改数据

1. 可读流 createReadStream

const fs = require("fs");
// 1. 创建可读流读取文件
let readStream = fs.createReadStream("hello02.text");
// 1.2 设置流的编码格式,默认utf-8,可省略
// readStream.setEncoding("utf-8")
// 1.3 监听流读取数据,读取数据会触发data事件,如果数据量比较大,读取事件较长会多次触发data
let data = "";
readStream.on("data", function (chunk) {
  data += chunk;
});
// 1.4 流读取数据完成触发end事件
readStream.on("end", function () {
  console.log("数据读取完成", data);
});
// 1.5 流读取数据出错触发error事件
readStream.on("error", function (err) {
  console.log(err.message);
});

2. 写入流 createWriteStream

const fs = require("fs");
const str = "china very good";
let writeStream = fs.createWriteStream("test03.txt");
writeStream.write(str); // 把str内容写入到test03.txt文件
writeStream.on("finish", function () {
  // 写入完成触发的函数
  console.log("write ok");
});
writeStream.on("error", function (err) {
  console.log(err.message);
});

3. 管道流 pipe

把一个数据流通过流 流向另外一个流,如文件复制

const fs = require("fs")

let readStream = fs.createReadStream("text.txt")
let writeStream = fs.createWriteStream("txt1.txt")
// 读取流内容直接流到写如流
readStream.pipe(writeStream)

4. 链式流

多个流可以链接操作,如多个管道流链接使用

const fs = require("fs")
const zlib = require("zlib")

//如压缩文件:
fs.createReadStream("txt1.txt")
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream("txt2.txt.gz"))

// 解压文件
fs.createReadStream("txt2.txt.gz")
  .pipe(zlib.createGunzip())
  .pipe(fs.createWriteStream("txt3.txt"))

5. 模块作用域

commjs规范

nodejs的模块使用的commjs规范,模块的作用域是在模块内部。
模块第一次加载会被放入缓存
模块加载顺序: 1. 先从缓存 2. node.js 内置模块 3. 本地模块(node_modules或者自定义)

// 引入自定义模块
let user = require("./module/user")
const peo = require("./module/person")

两种写法:

// 默认导出的是一个对象,给导出对象添加属性
exports.name = "anna",
exports.age = 29,
exports.say = ()=>{
    console.log("say~~");
}

// 修改导出数据类型,可以导出一个对象或函数
module.exports = {
    name:"zhang",
    age:19,
};

es6模块(安装工具)

nodejs不支持es6模块
如果需要支持import语法,需要安装babel编译工具

  1. cnpm i babel-core babel-preset-env -S
  2. 在当前项目目录创建.babelrc的配置文件
{
    "presets": ["env"]
}
  1. 全局安装 cnpm i -g babel-cli
  2. 使用babel-node xxx.js 执行js文件
import esUser from "./modules/es6user";

三、

  1. nodejs只保留的基础的js功能,没有DOM,BOM对象。因为node.js没有浏览器环境。
  2. node.js 没有window对象,nodejs的全局变量是global,nodejs的全局变量都是global对象的属性

1. 全局变量 global

//1 隐式定义(不声明变量,直接赋值)
test = "a1";
console.log(test, global.test);

//2 直接把变量作为属性添加到global对象上
global.test2 = "test2";
console.log(global.test2);

2、nodejs提供的常用全局变量

// 1. __filename 输出当前执行文件的绝对路径
console.log(__filename);
// 2. __dirname 输出当前执行文件目录的绝对路径
console.log(__dirname);

// 3. 保留了定时器的函数(setTimeout,clearTimeout,setInterval,clearInterval)
// 4. process 用于描述当前node进程状态,也是提供了一个与操作系统交互的接口(了解)
process.stdout.write("hello process"); // 打印在终端上

2. 工具函数 util模块

const util = require("util");

// 1. 判断各类数据类型的函数
let arr = [];
console.log(util.isArray(arr));

// 2. callbackify 将async异步函数或者返回值为promise对象的函数转为回调函数风格
async function f1() {
  return "hello async";
}
const f1back = util.callbackify(f1);
f1back(function (err, data) {
  if (!err) {
    console.log(data);
  }
});

//3. inspect(object[,bool,[deep,[colors]]]) 将一个对象转为字符串
// object 对象
// bool 显示对象的隐藏信息,默认是false
// deep 显示对象的层数,默认只显示2层,null则是全显示
// colors 属性值的颜色
let users = {
  name: "zhang",
  age: 12,
  address: {
    city: "chengdu",
    family: [
      {
        name: "li",
        age: 42,
        frend: {
          name: "wang",
          age: 12,
        },
      },
    ],
  },
};
console.log(util.inspect(users, true, null));
  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值