nodejs

141 阅读3分钟

node.js

查看本机安装的node.js命令:node -v
注意事项:不能使用BOMDOMAPI,顶级对象是globalglobalThis(推荐)(这两个相等)

Buffer

缓冲区

本质是一段内存空间,专门用来处理二进制数据。

// 第一种
const bufferOne = Buffer.alloc(10); // 安全,10个字节
// 第二种
const bufferTwo = Buffer.allocUnsafe(10); // 速度快,但不安全可能有旧数据
// 第三种
const bufferThree = Buffer.from("lxh"); // buffer中存储的是十六进制,lxh会转为Unicode编码,再转为十六进制
const bufferFour = Buffer.from([108, 120, 104]); // 这里面的是十进制
bufferFour.toString() // 转为字符串 lxh
bufferFour[0] // 拿到的是十进制 108
bufferThree[0] // 拿到的是十进制 108
bufferThree[0].toString(2) // 拿到的是十进制转二进制 1101100
bufferThree[0] = 95 // 修改 注意这里是十进制,最大255,如果超出,舍去高位的数字(最长8位,多的舍去前面的数字)
const bufferFive = Buffer.from('中国') // 一个汉字站三个字节

运行node

node 路径/文件
使用插件nodemon
安装npm i -g nodemon
nodemon 路径/文件

path模块

image.png

const path = require("path");

// __filename、__dirname

// '/a'和'./a'是一样的
path.join('/a', '/b/c', '../', '/d/e/f', '../../')
// 输出 \a\b\d

path.resolve() // 和path.join()差不多

path.basename('/a/b/c/d/e/index.html') // 获取基础名称
// 输出 index.html
path.basename('/a/b/c/d/e/index.html', '.html') // 获取文件名
// 输出 index

path.extname('/a/b/c/d/e/index.html') // 获取扩展名
// 输出 .html

path.parse('../lxh.vue') // 路径信息
// { root: '', dir: '..', base: 'lxh.vue', ext: '.vue', name: 'lxh' }

path.dirname("../lxh/xxx.js") // 获取文件夹名
// ../lxh

fs模块

导出:module.exports
引入:require()

exportsmodule.exports指向同一个对象
exportsmodule.exports同时使用时得到的永远是module.exports
注意:为了混乱,建议不同时使用exportsmodule.exports
exports.age = 24
module.exports = {name: 'xxx'}
// 得到{name: 'xxx'}

module.exports.age = 24
exports = {name: 'xxx'}
// 得到{age: 24}

module.exports.age = 24
exports.name = 'xxx'
// 得到{age: 24, name: 'xxx'}

读取文件

const fs = require("fs");

const path = require("path");

fs.readFile(path.join(__dirname, "demo.txt"), 'utf8', (err, data) => {
  if (err) {
    console.log(`读取文件失败${err.message}`);
  }
  console.log(`读取文件成功:${data}`);
});

fs.readFileSync() // 同步

写入文件

const fs = require("fs");

const path = require("path");
// 这种方式是默认是覆盖
// 追加的话写第三个参数{flag: "a"}(一般日志,访问记录用追加)
fs.writeFile(path.join(__dirname, "demo.txt"), {flag: "a"}, "xxxx content", (err) => {
  if (err) {
    console.log(`写入文件失败${err.message}`);
    return
  }
  console.log(`写入文件成功`);
}); // 异步

fs.writeFileSync() // 同步

追加

const fs = require("fs");
// 注意异步有回调函数,同步没有
fs.appendFile() // 异步
fs.appendFileSync() // 同步

流式

适用于频繁和大文件写入的时候

写入

const path = require("path");
const fs = require("fs");

const _stream = fs.createWriteStream(path.join(__dirname, "lxh.txt"));
_stream.write("你好\r\n")
_stream.write("lxh\r\n")
_stream.close()

读取

const fs = require("fs");

const _read = fs.createReadStream('./lxh.txt', "utf-8")
_read.on('data', chunk => {
    console.log(chunk);
})

_read.on("end", () => {
    console.log("读取完成");
})

文件移动和重命名

const fs = require("fs");
fs.rename()
fs.renameSync()

文件删除

const fs = require("fs");
fs.unlink()
fs.unlinkSync()
fs.rm()
fs.rmSync()

文件夹的操作

const path = require("path");
const fs = require("fs");

// 创建,{recursive: true}递归创建
fs.mkdir(path.join(__dirname, "a/b/c"), {recursive: true}, (err) => {
  if (err) {
    console.log("失败", err);
    return;
  }

  console.log("成功");
});
fs.mkdirSync();

// 读取
fs.readdir();
fs.readdirSync();

// 删除
fs.rmdir("/a", {recursive: true}, (err) => {}); // 不推荐,因为{recursive: true}将来会移除
fs.rmdirSync();
fs.rm(); // 建议使用
fs.rmSync();

查看资源状态

const fs = require("fs");

fs.stat('./lxh.txt', (err, data) => {
    console.log(data); // 信息
    console.log(data.isFile()); // 判断是否是文件
    console.log(data.isDirectory()); // 判断是否是文件夹
})

创建基本的web服务器

const http = require("http");

// 创建web服务器实例
const server = http.createServer();

// 为服务器绑定request事件
server.on("request", (req, res) => {
  // req.url请求路径、req.method请求类型、req.headers请求头
  // res.end向客户端返回数据,英文没有问题,但是中文乱码
  // 解决中文乱码下面这句
  res.setHeader('content-type', 'text/html;charset=utf-8')
  
  // 获取请求体
  let _body = ""
  req.on("data", chunk => {
    _body += chunk
  })
  req.on("end", () => {
    console.log(_body);
    res.end("结束啦")
  })
  
    // 获取请求路径和参数
      //   方法一
      const _urlObj = url.parse(req.url, true);
      console.log(_urlObj.pathname);
      console.log(_urlObj.query);

      //   方法二(推荐)
      const _url = new URL(req.url, "http://127.0.0.1");
      console.log(_url.pathname);
      console.log(_url.searchParams);
      console.log(_url.searchParams.get("name"));
      
      res.statusCode = 222; // 设置响应状态码
      res.statusMessage = "lxh"; // 设置响应状态描述(中文要报错)
      res.write("finished");
      res.end();
});

// 监听端口,启动服务器,如果是80,可以省略:80
server.listen(8090, () => {
  console.log(`服务器启动了,运行在:http://127.0.0.1:8090`);
});

// 使用插件moment,需要安装
const moment = require("moment");

console.log(moment().format("YYYY-MM-DD HH:mm:ss"));

express

基于 Node.js 平台,快速、开放、极简的 Web 开发框架

安装:npm install express --save

搭建基本服务器

const express = require("express");

const app = express();

app.get("/table", (req, res) => {
  // req.query默认是空对象,获取客户端传过来的数据?id='xxx'&search='yyy'
  // req.params默认是空对象,获取客户端传过来的数据/:id/:search
  // 对象需要JSON转换
  res.end(JSON.stringify({ name: "lxh", age: 25 }));
});

app.post("/user", (req, res) => {
  res.end("lxh");
});

app.listen(80, () => {
  console.log("express server running at http://127.0.0.1");
});

托管静态资源

const express = require("express");

const path = require("path");

const app = express();

// 可以写多个,http://127.0.0.1/lxh.html
app.use(express.static(path.join(__dirname, "/html")));
// http://127.0.0.1/static/lxh.html
app.use('/static', express.static(path.join(__dirname, "/html")));

app.listen(80, () => {
  console.log("express server running at http://127.0.0.1");
});

通过html文件夹下面的文件,html目录不存在url中

路由

// 挂在路由
app.post("/user", (req, res) => {
  res.end("lxh");
});

// 路由的模块化
新建router.js文件
const express = require("express");

const router = express.Router();

router.get("/user", (req, res) => {
  res.end("str");
});

module.exports = router;

注册路由
const router = require(./router.js)

app.use(router)
app.use('/api', router) // 访问需要加前缀/api

中间件

全局中间件,可以定义多个
const mw = (req, res, next) => {
  // req.xxx在路由的req可以访问到req.xxx
  console.log("中间件");
  next(); // 一定要写next()不然请求一直处于加载状态
};

app.use(mw)

局部中间件,可以写多个
const mw = (req, res, next) => {
  console.log("中间件");
  next();
};

app.get("/xxx", mw, (req, res) => {
  res.end("局部");
});
// 定义多个局部中间件
app.get("/xxx", mw1,mw2, (req, res) => {
  res.end("局部");
});
app.get("/xxx", [mw1,mw2], (req, res) => {
  res.end("局部");
});

错误级别的中间件多一个参数
app.use((err, req, res, next) => {
    console.log(`发送错误:${err.message}`)
    next()
})
// 注意:错误级别的中间件必须放到所有路由之后

内置的中间件
express.static()
express.json()
express.urlencoded()

配置解析application/json格式数据的内置中间件
app.use(express.json())
配置解析application/x-www-form-urlencoded 格式数据的内置中间件
app.use(express.urlencoded({ extended: false }))
// 这俩个通过req.body获取客户端传过来的数据

第三方中间件
body-parser
需要安装
const bp = require('body-parser')

app.use(bp.json())
app.use(bp.urlencoded({extended: false}))

解决跨域

cors有一系列http响应头组成,配置cors相关的响应头就能解决跨域
使用cors中间件,安装npm i cors
const cors = require('cors')
app.use(cors())

cors三个响应头
Access-Control-Allow-Origin
res.setHeader('Access-Control-Allow-Origin', '*')

Access-Control-Allow-Headers
res.setHeader('Access-Control-Allow-Headers', 'Content-type, X-Custom-Heaher')

Access-Control-Allow-Methods
// 默认情况仅支持GET、POST、HEAD请求
res.setHeader('Access-Control-Allow-Methods', '*')

koa

基于Node.js平台的下一代web框架

安装:npm i koa

搭建基本服务器

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(80, () => {
    console.log(`koa server running at http://127.0.0.1`)
});

路由

安装:npm i koa-router

const Koa = require('koa');
const Router = require('koa-router')

const app = new Koa();
const router = new Router({prefix: '/xxx'}); // prefix前缀

router.get(`/`, async (ctx) => {
    // ctx里包括request、response
    ctx.body = '首页'
})

app.use(router.routes());

app.listen(80, () => {
    console.log(`koa server running at http://127.0.0.1`)
});

跨域

安装:npm i koa2-cors

const cors = require('koa2-cors')

app.use(cors())