Node.js核心模块(内置模块)

2,726 阅读8分钟

Node.js概念

什么是Node.js

  • Node.js 是一个基于 Chrome V8 Java 引擎的 JS 运行环境
  • nodejs可以看做是一个平台,是一个运行环境。可以让我们脱离浏览器来运行JavaScript代码。
  • 浏览器中的js只能操作DOM元素。不能读写文件,不能搭建网络服务,不能操作数据库。node可以。

JavaScript与Node.js的区别

JAVASCRIPTNODEJS
客户端技术,在浏览器运行服务器端技术,与Java,PHP,C++等是后端语言(平台环境)
有多种解析器可以使用只能运行于Chrome的V8引擎下。
有兼容问题只有一个解析器,不存在兼容问题
ES语法,浏览器API(BOM,DOM)ES语法,node内置API(模块),第三方API(模块)
主要用于网页DOM操作,实现用户交互效果主要用于实现服务器端的运行逻辑,如访问数据库,文件读写等

安装Node和操作使用

安装

  • node官网:nodejs.org/zh-cn/
  • node的镜像中文网:nodejs.cn cmd框中输入node-v,成功输出版本号就说明node安装成功!

image-20211217202741096.png

使用

  • 执行js文件------js文件所在的当前目录下输入node XXX.js就行了(输入文件名时,可以通过tab键自动补全。)
  • ↑键可以获取上次输入的命令 image-20211217203053284.png
  • 按下esc可以清空当前输入的命令
  • 命令行输入cls 可以清屏

Node模块

模块的导入和导出

导出

新建一个a.js文件,里面的代码如下:

//导出一个对象,对象中的信息就会被暴露
module.exports = {
    name:"onion",
    act(){
        console.log("之前我没得选,现在我想做一个好人")
    },
    age:24
}

导入

新建一个b.js文件,里面的代码如下:

const info = require("./a.js")
console.log(ldh.age)//25
console.log(ldh.name)//onion
ldh.act();
//或者使用解构赋值
const {name} = require("./a.js") //只接受name的值
console.log(name)//onion

注意

  • module.exports = { name:‘onion’} module.exports.name = 'onion'的区别;前者是创建的新的对象,将原对象覆盖。后者是在原对象上添加一个新的name属性。
  • require()方法的返回值其实就是引入模块的module.exports对象。require方法加载其他模块时,会执行被加载模块中的代码。

exports导出

由于module.exports写起来比较繁琐,node官方为我们提供了exports关键字,它和module.exports指向同一个对象。

exports.name = "onion";
exports.age = 25;
exports.act = function () { console.log("以前我没得选,现在我想做一个好人"); };

两个导出的区别

exports和module.exports其实指向的是同一个对象

console.log(module.exports == exports); // true

注意:module.exports指向谁,谁就是被导出的对象。导出多个变量和方法用exports

使用场景

1.module.exports指向一个新对象, exports添加一个新属性。

module.exports = {
  name:"onion",
  age:25
}
exports.myName = "onion韩";
//导出的结果为 :{ name:"onion", age:25}

2.exports 指向一个新对象,module.exports 添加一个新属性

exports = {
  name:"onion",
  age:25
}
module.exports.myName = "onion韩";
//导出的结果为 :{ myName:"onion韩"}

3.module.exports 添加一个新属性, exports添加一个新属性。

module.exports.myName = "onion韩";
exports.name = "onion";
exports.age = 25;
//导出的结果为:{ myName: 'onion韩', name: 'onion, age: 25 }

核心模块(内置模块)

核心模块由node官方提供。常见的有:fs,path,http等

fs模块(对文件的操作)和

文件读取-fs.readFile

fs.readFile(filename,[encoding],[callback(error,data)]
//第一个必选参数:表示读取的文件名。
//第二个参数:是可选的,表示文件字符编码(例如:Utf-8)。
//第三个参数`callback`是回调函数,用于接收文件的内容(回调函数的两个参数 error 和 data , err 表示错误的提示,有则出错无则没有错误;data 是文件内容。 如果指定 encoding , data是一个解析后的字符串,否则表示二进制数据)。

eg1:

//引入fs模块
const fs = require('fs');
//引入path模块
const path = require('path');
//文件路径
const filePath = path.join(__dirname,'File.txt')
const filePath1 = path.join(__dirname,'File1.txt')
fs.readFile(filePath,'utf8',function(err,data){
    console.log(data);
});

文件写入fs.writeFile(使用方法和读取类似)

语法格式

fs.writeFile(filename,data,[options],callback)
//第一个必选参数:表示读取的文件名
//第二个参数:要写的数据
//第三个参数:是一个对象,如下↓
encoding {String | null} default='utf-8'
mode {Number} default=438(aka 0666 in Octal)
flag {String} default='w'

eg2

// 写入文件内容(如果文件不存在会创建一个文件)
// 写入时会先清空文件
fs.writeFile(filePath, '写入成功', function(err) {
    if (err) {
    //如果出错,抛出错误
        throw err;
    }
    // 写入成功后读取测试
    var data=fs.readFileSync(filePath, 'utf-8');
    console.log(data);
});

文件追加-appendFile

fs.appendFile(filename, data, [options], callback)
//第一个必选参数:表示读取的文件名
//第二个参数:可以是任意字符串或者缓存
//第三个参数 option 是一个对象,与write的区别就是[options]的flag默认值是”a”,所以它以追加方式写入数据.

eg3

// 写入文件内容(如果文件不存在会创建一个文件)
fs.appendFile(filePath, '追加的内容', function(err) {
    if (err) {
        throw err;
    }
    // 写入成功后读取测试
    var data=fs.readFileSync(filePath, 'utf-8');
    console.log(data);
});

path模块

path模块包含了一系列处理和转换文件路径的工具集合,不同操作系统的路径分隔符是不同的。 window下是\ linux是/。

path.jion()

链接路径:大多数情况下在node中我们选择的是绝对路径,因为相对路径相对的是我们命令行所打开的目录

const fs = require("fs");
//引入path路径
const path = require("path")

console.log("手动拼接:"+__dirname+"\\a.txt");
console.log("path模块:"+path.join(__dirname,"a.txt"));

fs.readFile(path.join(__dirname,"a.txt"),"utf-8",function (err,data) {
    if (err) {
        console.log(err);
        return;
    }
    console.log(data);
})

Tips

  • __dirname返回当前目录的父级目录 , 不属于path模块,每个自定义模块都有

  • __filename返回当前文件的绝对路径,包含文件名。不属于path模块,每个自定义模块都有

  • path.extname(path)返回路径中的文件的后缀名。

  • path.basename(path,[ext])返回文件的文件名(包含后缀),如果指定了第二个参数,则表示 将该后缀删除。

http模块

http意为传输协议(客户端以什么样的形式发送数据给服务器端↔服务器端以什么样的形式发送数据给客户端)

搭建一个服务器

//1.引入http模块,用于搭建服务器。
const http = require("http");
//2.创建服务,传入一个回调函数.当有请求进来的时候,该回调就会执行。
//req:请求对象  包含请求信息和对应的方法
//res:响应对象  包含响应信息和对应的方法
let app = http.createServer((req,res)=>{
 //3.当有请求进来,我们给浏览器一个响应。
  res.end("<h1>hello,boy</h1>");
});
//4.添加端口监听   每一个软件启动都需要一个端口
app.listen(3000);
//这是一条提示信息而已
console.log("服务已启动!");

常用的请求方式

  • get(get的语义是获取的意思。 如果要从服务器端获取数据,则使用get) get的参数会在地址栏显示,不安全。

  • post(post的语义是邮寄的意思。如果要将本地的数据推送给服务器端,则使用post)post的参数不会在地址栏显示,安全。

Tips

常见的状态码:

  • 200:成功 2开头的都表示成功

  • 404:请求的资源不存在。 4开头的都表示客户端错误。

  • 302:重定向。 类似于生活的呼叫转移。

  • 500:服务器端错误。

补充:

www.mi.com/redminote11…

mi.com表示小米的服务器,redminote11pro 表示这台服务器上的具体资源。 id=1是客户端发送给服务器端的数据

案例(获取请求地址栏的传参数)

当我们打开某个网页的时候,会有这个情况如下,地址栏中的信息发生变化,我们页面的数据也会发生变化。如下:

下载.gif 那么,利用我们今天介绍的模块该如何来实现呢?利用我们写js的逻辑可能你会这样来实现↓

// 引入http模块
const http = require('http');
// 引入fs模块
const fs = require("fs");
// 引入路径模块
const path = require("path");
// 创建服务
http.createServer(function (req, res) {
  // 考虑到可能有的小伙伴还没学习数据库,这里我们就把数据存在一个arr里面了!!!
  let arr = ["商品1", "商品2", "商品3", "商品4", "商品5", "商品6"];
  // 标头
  res.writeHead(200, {
    'Content-Type': 'text/html;charset=utf-8'
  });
  // 如果请求的url是/?page=2则执行
  if (req.url == "/?page=2") {
    res.end(`
    <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <body>
    <ul>
      <li>${arr[3]}</li>
      <li>${arr[4]}</li>
      <li>${arr[5]}</li>
    </ul>
  </body>
  </html>`)
  } else {
    res.end(`
    <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <body>
    <ul>
      <li>${arr[0]}</li>
      <li>${arr[1]}</li>
      <li>${arr[2]}</li>
    </ul>
  </body>
  </html>`)
  }
}).listen(3001);
console.log('Server running at http://127.0.0.1:3001/');

可以在浏览器地址栏输入对应信息来测试。不过这样写的话是不是也太麻烦了😂 总不能有一个页面我们就写一个页面都把他们放到这个js文件中吧,那么应该如何实现呢?

// 引入http模块
const http = require('http');
// 引入url模块(URLSearchParams 可以对 get请求过来的参数进行解析,将查询字符串转为一个对象。通过该对象的get方法来获取相应的值。)
const {URLSearchParams} = require("url")
// 创建服务
http.createServer(function (req, res) {
  // 禁止请求图标
  if (req.url == "/favicon.ico") {
    res.end("")
    return
  }
  // 存储数据的arr
  let arr = ["商品1", "商品2", "商品3", "商品4", "商品5", "商品6","商品7", "商品8", "商品9"];
  // 标头信息
  res.writeHead(200, {
    'Content-Type': 'text/html;charset=utf-8'
  });
  //解析查询字符串(会将http://127.0.0.1:3001/?page=2&pagesize=3会从问号处后面开始解析内容)   
  let params = new URLSearchParams(req.url.substring(2));
  console.log(params);//  打印结果:URLSearchParams { 'page' => '2', 'pagesize' => '3' }
  //获取页码
  let page = params.get("page");
  //获取当前页的数据量
  let pagesize = params.get("pagesize");
  //如果用户没有传page的值,默认是第一页
  if (!page) {
    page = 1;
  }
  //如果用户没有传pagesize的值,默认是3条
  if (!pagesize) {
    pagesize = 3;
  }
  res.write("<ul>")
  //默认:第一页  0-2     第二页 3-5      第三页 6-8 ,修改pagesize值会改变,但是规律是不变的
  for (let i = (page-1)*pagesize; i < page*pagesize; i++) {
     res.write(`<li>${arr[i]}</li>`)
  }
  res.write("</ul>")
  res.end()
}).listen(3001);
console.log('Server running at http://127.0.0.1:3001/');

这里我们使用了一个内置模块url,用到了url.searchParams方法,它可以对 get请求过来的参数进行解析,将查询字符串转为一个对象。通过该对象的get方法来获取相应的值。还用到了substring方法:会将http://127.0.0.1:3001/?page=2&pagesize=3会从问号处后面开始解析直至最后。这样我们就能够实现开始的那种效果了。