node 基础相关模块知识

183 阅读1分钟

004535-1708793135e16f.jpg

node 基础相关模块知识

一、先来个基础全局

创建监听80端口,服务监控请求,获取html,图片和post数据(下面是文件,图片自己找一个吧)

24A0BA65-CFB4-4e09-AFDC-489F29658365.png

1.1 server.js
const http = require('http')
const server = http.createServer()
const fs = require('fs')
const url = require("url")
const querystring = require('querystring') //把2进制转成对象
server.listen('80', function () {
    console.log("【监听80端口】http://127.0.0.1:80",);
})
​
server.on('request', function (req, res) {
​
    if (req.method === 'GET') {
        const query = url.parse(req.url, true)
        console.log("query", query.query.name);
        if (!/(jpg|png|jpeg)$/.test(req.url)) {
            fs.readFile('./index.html', function (err, data) {
                // res.setHeader("content-type","text/html;charset-utf-8")
                res.end(data)
            })
        } else {
            fs.readFile('./gezi.jpg', function (err, data) {
                res.end(data)
            })
        }
    } else if (req.method === 'POST') {
        //获取客户端的传递过来的数据 req有监控data方法,也就是监控你post请求传递过来的参数
        let data
        req.on('data', function (d) {
            console.log("~~~~~~~~~~~~~", d);
            data += d
        })
        //监控客户端传参结束
        req.on('end', function () {
            console.log("option参数", querystring.parse(data));
            fs.readFile('./index.html', function (err, data) {
                // res.setHeader("content-type","text/html;charset-utf-8")
                res.end(data)
            })
        })
​
    }
})
1.2 index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .pic {
        width: 100px;
        height: 100px;
      }
    </style>
  </head>
  <body>
    <h1>你好啊</h1>
    <img class="pic" src="./gezi.jpg" alt="" />
    <form action="./" method="post">
      <div><span>姓名</span><input type="text" name="username" /></div>
      <div>
        <span>性别</span>
        <select name="age">
          <option value="1"></option>
          <option value="2"></option>
        </select>
      </div>
      <button type="submit">提交</button>
    </form>
  </body>
</html>

然后在控制台输入

node server.js

2EF40625-D9D3-4a8f-BAB6-1BDA27FFECDE.png

二、node基础模块

2.1 path模块

新建path.mjs文件 然后

node path.mjs启动
2.1.1 path.join

描述: 将多个路径拼接成一个相对路径 (或绝对路径,取决于第一个路径是否为根路径)

import path from "path"
console.log(path.join('a','b','c')); //a/b/c
console.log(path.join(process.cwd(),'/hello','word')) //C:\Users\admin\Desktop\node-related\node-related\nodeModel\hello\word
2.1.2 path.resolve

描述: 将多个路径拼接成一个绝对路径,返回一个解析后的绝对路径。

console.log(path.resolve('a', 'b', 'c')) 
//C:\Users\admin\Desktop\node-related\node-related\nodeModel\a\b\c  
console.log(path.resolve('/hello', 'world', './a', 'b')) //\hello\world\a\b
2.1.3 path.dirname:

描述: 返回路径中的目录名。

import path from "path"
console.log(path.dirname("a/b/c.js")); // a/b
console.log(path.dirname("a/b/c")) //a/b
console.log(path.dirname(process.cwd()));
//C:\Users\admin\Desktop\node-related\node-related
2.1.4 path.basename:

描述: 返回路径中的文件名,并可选地去除给定的文件扩展名。

import path from "path"
console.log(path.basename('a/b/c.js')) //c.js
console.log(path.basename('a/b/c.js', '.js'))//c
console.log(path.basename('a/b/c.js', 'js'))//c.
console.log(path.basename('a/b/c.js', 's'))//c.j
2.1.5 path.extname:

描述: 获取路径中的文件扩展名。

console.log(path.extname('a/b/c.js')) // .js
console.log(path.extname('a/b/c')) // 无打印
console.log(path.extname('a/b/c.d.ts')) // .ts
console.log(path.extname('a/b/.npmrc')) // 无打印
2.1.5 path.parse:

描述: 用于解析文件路径,将其拆分为一个对象。

import path from "path"
console.log(path.parse('/home/user/dir/file.txt'))
//{root: '/',dir: '/home/user/dir',base: 'file.txt',ext: '.txt', name: 'file'}

2.2 fs模块

新建fs.mjs文件 然后

node fs.mjs
2.2.1 fs.readFileSyncreadFile

描述: 读取文件内容,下面分别是 3 种写法,日常开发中常用 同步操作 和 Promise形式异步操作。

fs.readFileSync(params1,params2)

params1:设置要读取的文件路径 (相对或者绝对);

params2: 设置读取的编码格式。

fs.readFile((params1,params2,params3)

params1:设置要读取的文件路径 (相对或者绝对);

params2: 设置读取的编码格式。

params3: 回调函数。

const syncData = fs.readFileSync('./test.json', 'utf-8')
console.log(syncData);  // {"name":"张三","age":18 }
​
// 回调 形式 异步读取
fs.readFile('./test.json', 'utf-8', function (err, data) {
  if (!err) {
    console.log(data); // {"name":"张三","age":18 }
  }
})
​
// promis 写法
const data = await fs.promises.readFile('./test.json', 'utf-8')
console.log(data); // {"name":"张三","age":18 }
2.2.2 fs.writeFileSync(params1,params2,params3):

描述: 写入文件

params1:输出文件路径;

params2:输出内容;

params3 (可选):编码格式。

fs.writeFileSync('./testWrite.txt', '哈喽')

写入二进制文件 (读取一个图片,然后输出到一个新的位置)。

const imgBuf = fs.readFileSync('./rsegezi.jpg') // 返回一个二进制文件
console.log("imgBuf", imgBuf);
console.log('isBuffer', Buffer.isBuffer(imgBuf), 'bufferSize', imgBuf.length) // isBuffer true bufferSize 502770// 写入到新文件
fs.writeFileSync('newLogo.png', imgBuf, 'binary')
2.2.3 fs.statSync:

描述: 1、通过fs.statSync 获取文件或者目录得基本信息 ;2、也可判断文件是否存在,3、判断是目录还是文件

返回的对象上还包含可直接调用的方案,用于判断文件类型。

console.log(fs.statSync('./test.json'));
const fileInfo = fs.statSync('./test.json')
console.log(fileInfo.isFile(), fileInfo.isDirectory());  // true false
const dirInfo = fs.statSync('../nodeModel')
console.log(dirInfo.isFile(), dirInfo.isDirectory()); // false true
 try {
  // 查询一个不存在的文件/目录信息(会抛出异常,需要自行捕获)
   fs.statSync('not_exist.txt')
 } catch (e) {
   console.log('文件不存在')
 }
2.2.4 fs.appendFileSync

描述: 追加输出,向文件末尾追加写入得内容

fs.appendFileSync('./testWrite.txt', "{ like: '排球' }")
2.2.5 fs.renameSync

描述fs.renameSync 方法用于文件移动,当然也可以是重命名文件

fs.renameSync('./rsegezi.jpg', './rsegezi.jpg')
// 移动文件
try {
  fs.renameSync('move.mjs', "path.mjs") //这里得如果第一个参数是move.mjs,第二个文件是path.mjs 那么move.mjs会被删除,path.mjs里面得内容会被move.mjs内容替换掉
} catch (e) { }
2.2.6 fs.unlinkSyncfs.rmSync

描述fs.unlinkSyncfs.rmSync 都可用于单文件删除。 当然后者还支持删除目录,递归删除子文件/目录等

try {
  fs.unlinkSync('./delete.js')// delete.js 会被删除
  fs.rmSync('./delete.js')
} catch (e) { }
2.2.7 fs.readdirSync

描述:通过 fs.readdirSync 获取文件夹下所有文件信息 默认情况下只会返回名称。

console.log(fs.readdirSync("../nodeModel"));
//可通过指定第二个参数 withFileTypes:true 使返回结果包含类型。
​
console.log(fs.readdirSync('../nodeModel', { withFileTypes: true }));
2.2.8 fs.mkdirSync

描述 : 使用 fs.mkdirSync 创建目录,可通过设置 recursive:true 来递归创建多级目录

fs.mkdirSync("../nodeModel/create",{recursive: true })
2.2.9 fs.rmdirSync

描述 : 可以使用 fs.rmdirSync 删除目标目录,recursive: true 表明删除包含其子目录。

try {
  fs.rmdirSync("./create", { recursive: true })
} catch (error) {}
2.2.10 fs.watch

描述 : 使用fs.watch 监听目录得变更

fs.watch("../nodeModel", { recursive: true }, (eventType, filename) => {
  console.log(`File '${filename}' has changed: ${eventType}`)
})

2.3 util 模块

2.3.1 util.promisify(original)

描述:回调转promise;采用遵循常见的错误优先的回调风格的函数(也就是将 (err, value) => ... 回调作为最后一个参数),并返回一个返回 promise 的版本。 从而无需在函数内部使用async等待。

例子1:转换node里面的方法

const fs = require('fs')
const util = require('util')
​
// 将 fs.readFile() 转换为一个接受相同参数但返回 Promise 的函数。
const readFile = util.promisify(fs.readFile)
​
// 现在可以将 readFile() 与 await 一起使用!
const buf = await readFile('./package.json')
​
const obj = JSON.parse(buf.toString('utf8'))
console.log(obj.name) 

例子2:自定义函数

a: 函数最后一个参数不带有回调函数的
// 测试不带回调函数的方法
const callbackFn = (a, b) => {
  return a + b
}
const newCallbackFn = util.promisify(callbackFn); // 将带有回调的函数,转为返回promise对象
console.log("????newCallbackFn", newCallbackFn());//????newCallbackFn Promise { <pending> }newCallbackFn().then((result) => {
  console.log(result); // 不触发
}).catch(err => {
  console.error(err);// 不触发
});
​

newCallbackFn返回一个等待的Promise,不会触发then 和catch函数

b:函数最后一个参数是个函数,并且在函数内调用,注意必须要调用
// 测试带有回调函数的方法
const callBackHas = (a, callback) => {
  callback && callback()
}
​
 const newCallBackHas = util.promisify(callBackHas);
  newCallBackHas(2).then((res) => {
    console.log("res", res); // res undefined
  }).catch(e => {
    console.log("err", e); // 不触发
  });
​

为什么是undefined呢??? 因为then里面的res来源于callback的第二个参数,catch里面的e来源于callback的第一个参数,如果callback里面的第一个参数有值那么不走then,走catch,如果callback里面的第一个参数为null,那么走then;

// 测试带有回调函数的方法
const callBackHas = (a, callback) => {
  callback && callback(null12)
}
​
 const newCallBackHas = util.promisify(callBackHas);
  newCallBackHas(2).then((res) => {
    console.log("res", res); // res 12
  }).catch(e => {
    console.log("err", e); // 不触发
  });
// 测试带有回调函数的方法
const callBackHas = (a, callback) => {
  callback && callback(6612)
}
​
 const newCallBackHas = util.promisify(callBackHas);
  newCallBackHas(2).then((res) => {
    console.log("res", res); // 不触发
  }).catch(e => {
    console.log("err", e); // err 66
  });
2.3.2 util.inspect()

描述:对象转为字符串 util.inspect(object, [options]),常与 console.log 搭配使用,可以友好的将对象转为字符串,打印更加友好。

参数: depth 用于控制展开的层级

const _inspect = util.inspect({ a: "name", age: 20, c: [1, 2, 3, { name: 1, cf: () => { } }], b: { name: "b", c: [1, 3, 5] } }, { depth: Math.Infinity });
console.log("_inspect", _inspect);

2.4 url模块

2.4.1 url.parse(url:string,opt:boolean)

描述:解析 URL 字符串,返回一个解析后的对象。

const _url = "https://juejin.cn/book/7304230207953567755/section/7304642570489954358?utm_source=course_list"
console.log("~~", url.parse(_url));
console.log("~~", url.parse(_url, true));
4B1A45F2-0ADD-4549-9F7C-EB8C84605F99.png 9D789BCF-0F5C-4572-B4FB-D60CA39FF067.png 如图:参数带不带true区别是query的格式

2.4.2 url.URL

描述:和全局的 URL 一样,创建一个 URL 实例,提供许多开箱即用的操作。

const testUrl = 'https://www.baidu.com?search=juejin'
console.log('url.URL === URL', url.URL === URL) // true
console.log(new URL(testUrl))

56F1AF8A-5270-41a4-9F29-D95A481CD277.png

2.5 readline模块

//创建一个实例
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
})
// 询问
rl.question('What is your name? ', (name) => {
  console.log(`Hello, ${name}!`)
  // rl.close()
})

rl.write('Hello, World!\n') //Hello, World!!

rl.setPrompt('node> ') // 设置提示符
rl.prompt() // 显示提示符
rl.on('line', (line) => {
  // 监听行事件
  switch (
    line.trim() // 去除收尾空白字符,进行简单的命令选择判断
  ) {
    case 'hello':
      console.log('world') // 输出 'world'
      break
    case 'exit':
      rl.close() // 关闭 readline 接口
      break
    default:
      console.log(`Say what? I might have heard '${line.trim()}'`) // 输出收到的指令
      break
  }
  rl.prompt() // 显示提示符
})

61E9EB10-0C28-4576-A552-5659B324D92D.png

2.6 timer 定时器

setTimeout(callback, delay[, ...args]): 在 delay 毫秒之后执行一次 callback

setInterval(callback, delay[, ...args]): 每隔 delay 毫秒执行一次 callback

setImmediate(callback[, ...args]): setImmediate 的执行时机是:在当前执行栈中的所有同步代码以及任何 I/O 回调之后,但是在任何新的定时器(如 setTimeout 和 setInterval)回调之前。然而,如果与 process.nextTick() 相比,process.nextTick() 总是会在 setImmediate 之前执行,前提是它们都在同一个事件循环迭代中被调用。

process.nextTick(callback[, ...args]): 在Node.js中,process.nextTick() 函数被用于将回调函数放置在事件循环的当前执行栈的尾部,即在当前执行栈中的所有同步代码执行完毕,在当前执行栈清空后,但在任何I/O回调(包括定时器回调如setTimeout和setInterval)之前执行

setImmediate(() => console.log('setImmediate'))//
setTimeout(() => console.log('setTimeout'), 0)//
process.nextTick(() => console.log('nextTick'))//最先执行
setInterval(() => console.log('setInterval'), 1000)//

输出顺序:nextTick
     setImmediate
     setTimeout
     setInterval