node.js 基础知识(二)

181 阅读8分钟
  • 知识要点
    • Node.js安装及使用
    • 通过Node.js搭建服务器
    • 模块化及自定义模块
    • 内置模块fs的使用
    • buffer及stream

Node.js介绍

Node.js 诞生于2009年,Node.js采用C++语言编写而成,是一个Javascript的运行环境。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境 ,让JavaScript的运行脱离浏览器端,可以使用JavaScript语言 书写服务器端代码。

1. 安装Node.js

Node.js官网下载稳定版本,node偶数版本为稳定版本,奇数版本为非稳定版本。

  • mac直接安装 或者brew来安装
  • 安装完Node.js会自动安装NPM(Node Package Manager):包管理工具;
  • 通过指令 node -v 来查看是否安装完成和查看node版本号;npm -v 来查看npm版本。

1.1 使用Node.js实现一个服务器

//引入http模块
let http = require("http");
//创建一个服务器
let serve = http.createServer((req,res)=>{
    console.log("hello");
    res.end("hello world");
})
//设置端口号
serve.listen(3000);

1.2 访问服务器

  • 本机访问
//第一种方式
localhost:端口号

//第二种方式
127.0.0.1:端口号
  • 外部访问
//首先通过命令行获取本机的ip地址
ipconfig

//通过ip地址访问
IP地址:端口号

1.3 更改服务器内容

//服务器更改内容后需要重启服务器才能刷新
//第一步:快捷键ctrl+c,重启服务器
//第二部:重新输入命令运行node.js,比如node http.js

1.4 安装nodemon

//全局安装nodemon
npm i nodemon -g

//解决系统禁止运行脚本

1.管理员身份打开powerShell

2.输入set-ExecutionPolicy RemoteSigned

   选择a或者y

3.如果还是不行,根据提示

输入Set-ExecutionPolicy -Scope CurrentUser运行即可,之后输入RemoteSigned回车运行即可,再次执行nodemon,发现成功了
  • Google Chrome 默认非安全端口列表,尽量避免以下端口。

    1, // tcpmux 7, // echo 9, // discard 11, // systat 13, // daytime 15, // netstat 17, // qotd 19, // chargen 20, // ftp data 21, // ftp access 22, // ssh 23, // telnet 25, // smtp 37, // time 42, // name 43, // nicname 53, // domain 77, // priv-rjs 79, // finger 87, // ttylink 95, // supdup 101, // hostriame 102, // iso-tsap 103, // gppitnp 104, // acr-nema 109, // pop2 110, // pop3 111, // sunrpc 113, // auth 115, // sftp 117, // uucp-path 119, // nntp 123, // NTP 135, // loc-srv /epmap 139, // netbios 143, // imap2 179, // BGP 389, // ldap 465, // smtp+ssl 512, // print / exec 513, // login 514, // shell 515, // printer 526, // tempo 530, // courier 531, // chat 532, // netnews 540, // uucp 556, // remotefs 563, // nntp+ssl 587, // stmp? 601, // ?? 636, // ldap+ssl 993, // ldap+ssl 995, // pop3+ssl 2049, // nfs 3659, // apple-sasl / PasswordServer 4045, // lockd 6000, // X11 6665, // Alternate IRC [Apple addition] 6666, // Alternate IRC [Apple addition] 6667, // Standard IRC [Apple addition] 6668, // Alternate IRC [Apple addition]

    6669, // Alternate IRC [Apple addition]

2. 模块化

一、为什么会有模块化

  • 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即,如今随着前端代码日益膨胀

    这时候JavaScript作为嵌入式的脚本语言的定位动摇了,JavaScript却没有为组织代码提供任何明显帮助,JavaScript极其简单的代码组织规范不足以驾驭如此庞大规模的代码;

二、Node.js中的模块化 commonjs规范

  • CommonJS就是为JS的表现来制定规范,因为js没有模块的功能所以CommonJS应运而生,它希望js可以在任何地方运行,不只是浏览器中。

2.1 自定义模块

2.1.1 引入模块

  • 引入——文件形式模块

    home.js执行文件

    //通过require来引入
    require("./aModule"); //注意一定要有"./",文件后缀可加可不加。
    

    amodule.js文件

    console.log("我是被引的amodule.js模块");
    
  • 引入——文件夹形式模块

    • home.js执行文件
    require("./aModuleDir"); //必须加"./"
    

    ​ 会自动查找aModuleDir文件夹下的index.js文件执行

    console.log("我是aModule模块文件夹里的index.js");
    
    • 当然也可以配置默认启动文件,在文件夹内新建package.json来指定执行文件
    {
      "name":"aModule",
      "version":"1.0.0",
      "main":"test.js"     //test.js取代index.js成为默认启动文件
    }
    

2.1.2 导出模块

  • 自定义模块的按需导出

第一种导出方式:通过 module.exports 导出; ___dirname , __filename

module.exports = {
    a:"我是a的值",
    b(){
        console.log("我是导出的b函数");
    }
}

引入导出文件

let mymodule = require("bModule");
console.log(mymodule.a);
mymodule.b();

第二种导出方式:通过 exports来导出

exports.fn = function(){
    console.log("我是fn函数");  
}

导入文件

let myfn = require("bModule").fn;
myfn();
// 或者 通过解构赋值 
let { fn } = require("bModule");
fn();
  • 模块加载的优先级 ,先文件再目录;

2.2内置模块;

nodejs内置模块有:Buffer,C/C++Addons,Child Processes,Cluster,Console,Cr

ypto,Debugger,DNS,Domain,Errors,Events,File System,

Globals,HTTP,HTTPS,Modules,Net,OS,Path,Process,P unycode,Query Strings,Readline,REPL,Stream,String De coder,Timers,TLS/SSL,TTY,UDP/Datagram,URL, Utilities,V8,VM,ZLIB;内置模块不需要安装,外置模块需要安装;

2.3第三方模块(外置模块)

通过npm下载第三方模块,放到node_modules文件夹里

//先在mytest文件夹下的index.js导出
module.exports = {
    a:10;
    b(){
        consoloe.log("我是b fn")
    }
}

//外部引入mytest
let {a,b} = require("mytest"); //解构赋值,这个文件夹不需要./
console.log(a);
b();

//执行结果
10
我是b fn

3. npm 包管理器

NPM(Node Package Manager) 官网的地址是 npm官网

  • npm常用指令;
    • npm init:引导创建一个package.json文件
    • npm help(npm -h) :查看npm帮助信息
    • npm version (npm -v) : 查看npm版本;
    • npm search:查找
    • npm install (npm i):安装 默认在当前目录,如果没有node_modules 会创建文件夹;
      • npm install module_name -S 或者--save 即 npm install module_name --save 写入dependencies 运依赖
      • npm install module_name -D 或者 —save-dev 即 npm install module_name --save-dev 写入devDependencies 开发依赖
      • npm install module_name -g 全局安装(命令行使用)
      • 指定版本安装模块 npm i module_name @1.0 通过 "@"符号指定;
    • npm update(npm -up):更新
    • npm remove 或者 npm uninstall:删除
    • npm root 查看当前包安装的路径 或者通过 npm root -g 来查看全局安装路径;所有项目需要的安装到全局
//package.json里的开发依赖与运行依赖
dependencies 运行依赖 比如jquery   安装时-S
devDependencies  开发依赖  比如less    安装时-D

// npm install   能自动安装package.json里面需要的包

4. fs 模块

  • fs是文件操作模块,所有文件操作都是有同步和异步之分,特点是同步会加上 "Sync" 如:异步读取文件 "readFile",同步读取文件 "readFileSync";

4.1 文件操作

(增删改查、复制)

4.1.1 读取文件(查)

  • 异步读取文件
let fs = require("fs");
fs.readFile("1.txt",(err,data)=>{
    if(err){
        return console.log(err);
    }
    console.log(data.toString());
})
  • 同步读取文件
let fs = require("fs");
let res = fs.readFileSync("1.txt");
console.log(res.toString());

4.1.2 写入文件(增)

let fs = require("fs");
//flag配置  "a":追加写入,"w":写入,"r":读取
fs.writeFile("2.txt","我是要写入的内容",{flag:"w"},err=>{
    if(err){
        return console.log(err);
    }
    console.log("写入成功");   
})

4.1.3 删除文件(删)

fs.unlink("2.txt",err=>{
    if(err){
        return console.log(err);
    }
    console.log("删除成功");
})

4.1.4 修改名称(改)

fs.rename("1.txt","5.txt",function (err) {
    if(err){
        console.log(err);
    }else{
        console.log("修改成功");
    }
});

4.1.5 复制文件(复)

  • 先读取文件再写入文件
// 1.txt是被复制的,4.txt是复制的

//第一种方法 
fs.copyFile("1.txt","4.txt",function (err) {
    if(err){
        console.log(err);
    }else{
        console.log("复制成功");
    }
});

//第二种方法 封装一个复制函数
function mycopy(src,dest){
   fs.writeFileSync(dest,fs.readFileSync(src));
}
mycopy("1.txt","4.txt");

4.2 目录操作(增删查、是否存在、详细信息)

4.2.1 创建目录

let fs = require("fs");

//创建一个11文件夹
fs.mkdir("11",err=>{
    if(err){
        return console.log(err);
    }
    console.log("创建目录成功");
})

4.2.2 读取目录

fs.readdir("11",(err,data)=>{
    if(err){
        return console.log(err);
    }
    console.log(data);
})

4.2.3 删除目录

//第一种:删除空目录
fs.rmdir("11",err=>{
    if(err){
        return console.log(err);
    }
    console.log("删除成功");
})

//第二种:删除非空目录,封装函数(也能删除空目录)

//思路:先把目录里的文件删除,再删除被清空的大目录
function removeDir(path) {
    //1.先把目录里的文件删除
    //读取要删除的大目录
    let data = fs.readdirSync(path);
    //遍历要删除的目录
    for (let i = 0; i < data.length; i++) {
        //定义子目录的路径
        let url = path + "/" + data[i];
        //判断子目录的类型,是文件夹还是文件
        let res = fs.statSync(url)
        if(res.isDirectory()){
            //如果子目录是文件夹,继续查找
            removeDir(url);
        }else{
            //如果子目录是文件,直接删除
            fs.unlinkSync(url);
        }
    }
    //2.删除被清空的大目录
    fs.rmdirSync(path);
}

removeDir("11");

4.2.4 判断文件/目录是否存在

fs.exists("4.txt",function (exists) {
    console.log(exists);
})

4.2.5 获取文件/目录的详细信息

fs.stat("11",(err,stat)=>{
    if(err){
        return console.log(err);
    }
    
    //获取文件/目录的详细信息
    console.log(stat);
    
    //判断是不是文件
    let res1 = stat.isFile();
    console.log(res1);
    
    //判断是不是目录
    let res2 = stat.isDirectory();
    console.log(res2);
})

5. buffer 缓冲区

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。

但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

Buffer类被引入到Node.js的API中,让其与二进制数据流的操作和交互成为可能

5.1 buffer的创建

5.1.1 直接创建

// node.js 6.0之前
let buffer = new Buffer(10);

// 新版的写法
let buffer = Buffer.alloc(10);

// 打印结果都是
<Buffer 00 00 00 00 00 00 00 00 00 00>

5.1.2 字符串创建

let buffer = Buffer.from("大家好");

// 打印结果
<Buffer e5 a4 a7 e5 ae b6 e5 a5 bd>

5.1.3 数组创建

let buffer = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5, 0xae, 0xb6, 0xe5, 0xa5, 0xbd]);
// 数组创建里面必须是16进制字符

// 打印结果
<Buffer e5 a4 a7 e5 ae b6 e5 a5 bd>

5.2 buffer转换tostring

let buffer = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5, 0xae, 0xb6, 0xe5, 0xa5, 0xbd]);
// 数组创建里面必须是16进制字符
console.log(buffer);
// 打印结果
<Buffer e5 a4 a7 e5 ae b6 e5 a5 bd>
    
// 转换为字符串
console.log(buffer.toString());  
// 打印结果
大家好

5.3 乱码的处理

5.3.1 第一种

let buffer1 = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5]);
let buffer2 = Buffer.from([0xae, 0xb6, 0xe5, 0xa5, 0xbd]);
console.log(buffer1.toString());
console.log(buffer2.toString());
// 打印结果,乱码了
大�
��好

// 连接两个buffer
let newbuffer = Buffer.concat([buffer1,buffer2]);
console.log(newbuffer.toString
// 打印结果
大家好

5.3.2 第二种

// 引入内置模块
let buffer1 = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5]);
let buffer2 = Buffer.from([0xae, 0xb6, 0xe5, 0xa5, 0xbd]);
let { StringDecoder } = require("string_decoder");
let decoder = new StringDecoder();
let res1 = decoder.write(buffer1);
let res2 = decoder.write(buffer2);
console.log(res1);
console.log(res2);
console.log(res1 + res2);
// 打印结果
大
家好
大家好

6.stream 流

在Node.js中,流(stream)就是一系列从A点到B点移动的数据,巨型数据会被分割成小块(chunks)进行传输。

  • stream流:流与数据处理方面密不可分
    • 流的原理
    • 流数据的获取
      • pipe
      • data
      • end
    • copy的流方法实现
    • 加载视图的流方法实现

总结

  • nodejs的安装及使用

  • 服务端及客户端

  • commonjs模块化

  • fs模块的使用(文件操作及目录操作)

  • stream

  • buffer