前端Node的实用方法

Node

一、什么是Node

Node是以基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动、非阻塞式I/O模型(I/O是 input/output的缩写,即输入输出端口,在传统的编程模式中,I/O操作阻塞了代码的执行,极大的降低了程序的效率),Node的出现让JavaScript 运行在服务端的开发平台,具有相当重要的意义

二、初识Node

1、路径

node通过ch切换路径到文件路径,node的工作路径如果不切换会导致操作的失败d:可以切换盘符,通过ch切换到工作文件

2、命令获取路径

在Node中,可以通过node命令来获取相对路径

*__dirname: 可以获取到当前js文件所属的目录的绝对路径.*

*__filename: 可以获取当前js文件的绝对路径.*

3、引入内置path模块

const fs = require('fs');
const path = require('path');
const fullPath =  path.join(__dirname, '/data');
console.log(fullPath);
fs.writeFile(fullPath, '么么哒!', 'utf-8', err=>{
    if(err) return console.log(err);
    console.log('yes yyds!!!');
});

4、Buffer

因为JavaScript语言自身只有字符串数据类型,没有二进制数据类型,但在处理TCP流或文件流时必须使用二进制数据,所以Node.js定义了一个专门存放二进制数据的缓存区Buffer,在读取文件时,返回data数据时Buffer类型,所以需要转换为字符串

fs.readFile('./data/1.txt',(err, data) => {
    if(err){
        return console.log('读取发生错误:'+err);
    }
   
    console.log( data.toString());
});

三、http模块

http的简单图解

image-20210525212009055

const http = require('http');
//创建1个服务
const server = http.createServer((request, response) => {
    response.end('Hello, Node.js!');
});
//监听服务
server.listen(3000, () => console.log('服务启动成功'));

1、示例-获取URL读取文件的内容

const http = require('http');
const fs = require('fs');
const path = require('path');

const server =  http.createServer((req, res) => {
    //1.将url 和 method 转换为小写
    req.url = req.url.toLowerCase();
    req.method = req.method.toLowerCase();
   
    const fullPath = path.join(__dirname, 'www', req.url);
   
    fs.readFile(fullPath, (err, data) => {
        if(err){
            //读取文件发生错误了. 路径错了.
            res.statusCode = 404;
            res.end();
        }else{
            res.end(data);
        }
    }); 
});
server.listen(80, ()=>console.log('服务正在监听'));

2、createServer的回调

1.执行时机:只要有来自客户端的HTTP请求,这个函数就会被执行

2.回调函数的两个参数

req对象,客户端向服务端发的数据都被封装在req对象中

req.url  可以获取请求时候的url及其参数
req.method  可以获取客户端请求服务端的方法,post/delete/put/patch/head等

res对象,客户端响应给服务端的数据全部被封装在其中,

res.setHeader(),响应数据新增响应头,通过Content-Type可以返回指定数据的类型

3、请求分为两部分

请求头,键值对,作用是告诉浏览器一些关键的信息

请求体,发给服务器的数据

4、响应分为两部分

响应头 键值对 作用: 浏览器会根据响应头中的数据可能会做出一些处理.

响应体 服务器真正返回给浏览器的数据. 浏览器会解析响应体中的数据.

响应数据
res.write() 向响应体中写入数据
res.end(); 结束响应写入的数据.

5、常见状态码

常见状态码:
200:  服务器处理请求成功
201:  处理成功 并且创建了新的资源
400:  浏览器发送给服务器的数据有问题,  一般都是参数传递错误.
      127.0.0.1/api/joke?num=10
401:  身份验证过期.或者没有验证.
403:  权限不足.
404:  资源不存在.
500:  服务器内部发生错误.

四、npm使用

1、初始化

npm init -y //保存了初始化项目的信息
package.json
其中dependencies: 记录了我们下载的插件和版本.
其中scripts属性.
我们可以将一些常用的命令保存在 package.json中的scripts属性中,
npm run xxx; 就可以执行对应的命令.(webstorm不需要,🤭)

2、下载包

npm install 包名@版本号

3、删除包

npm uninstall 包名

五、express模块

1    express对象.
       这个对象中就有一些方法.
       static

2    Application对象.
       其实就是我们创建的应用.

3    Request对象
       回调函数中的 第1个参数  req

4    Response对象
       回调函数中的 第2个参数  res
    
5    Router对象
       路由对象.
const express = require('express');//引入
//创建express应用(服务)
const app = express();
app.get(path,(req,res)=>{res.send()})
app.post(path,(req,res)=>{res.send()})
app.use()//
app.use('/api/student', stuRouter);//注册路由
app.use(express.urlencoded({extended: false}));//注册中间件
app.use(express.static('public'));//静态页面托管
req.query
req.body//设置中间件之后再使用

1、express模块的文件读取和写入(转换)

//读取本地文件生成五条随机数据
app.get('/api/v2/joke', (req, res) => {
    //从jokes.json文件中随机的取1条笑话.
    fs.readFile(path.join(__dirname, 'data/jokes.json'), 'utf-8', (err, data) => {
        if (err) {
            //发生错误. 500
            return res.status(500).send({
                code: 500,
                msg: '服务器内部发生错误'
            });
        }
        //读取的时候,没有发生错误.
        // 将读取出来的数据转换为一个数组.  读取出来的数据是1个字符串.
        const jokes = JSON.parse(data); // 8880
        //随机5个.
        // 产生5个随机的下标.
        const retunJokes = [];

        const set = new Set();
        while(set.size != 5){
            //产生的下标不能重复.
            const index = Math.floor(Math.random() * jokes.length);
            set.add(index);
        }
        //执行到这里,就代表set中存储了5个不重复的下标.
        // set   14   98   5412   27   49
        for(let index of set){
            retunJokes.push(jokes[index]);
        }

        res.send({
            code: 200,
            count: jokes.length,
            joke: retunJokes
        });

       
    });
});

app.listen(80, () => console.log('服务启动成功'));

2、express托管静态页面

//引入第三方模块
const express = require('express');
//调用服务
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
//127.0.0.1/static/index.html
//app.use('/static', express.static('public'));
app.listen(80, ()=>console.log('服务启动成功'));

六、module

image-20210525220027688

module.export和exports都是Node中的顶层对象,但是为了避免混淆,用module.exports完全足够,它默认是返回一个空对象,并且让其他的文件在引入的时候也可以进行使用,让各个文件之间有了联系

七、CommonJS规范

CommonJS规范是JavaScript的一种模块化规范,它规定了JavaScript如何进行分模块。而Node.js的模块化是遵循CommonJS规范.

//www.commonjs.org

模块化:

如果将所有的代码都写在1个文件中

  1. 难以维护
  2. 不利于团队开发.

将项目分为一个一个的模块,按照功能

不要把所有的代码写在同1个文件中,而是将代码按照功能分开 分开在一个一个的单独的模块中

分为三个模块

1、内置模块

2、文件模块

readFile: 异步读取文件
writeFile:  异步写入文件.

使用require函数一样可以加载文件模块。

3、第三方模块:本质是文件模块

八、router模块

1.创建router对象

const express = require('express');
const stuHandler = require('../handler/stuHandler.js');
const router = express.Router();

2.在router对象上注册路由

router.get('/delete', stuHandler.delete);//第一个参数是对应的url部分路径,第二个参数是逻辑处理模块对应的代码

router.post('/update', stuHandler.update);//第一个参数是对应的url部分路径,第二个参数是逻辑处理模块对应的代码

3.将router对象暴露出去 module.exports

九、逻辑处理模块

这块代码才是文件的核心部分,书写了具体的请求处理逻辑

以学生管理系统的删除功能的代码为例

module.exports.delete = (req, res) => {
    //1. 获取浏览器传递给服务器的id
    const { id } = req.query;
    //2.  判断有没有这个id  400
    if (!id) return res.status(400).send({ code: 400, msg: '参数错误' });
    //3.  有这个id 就去学生库中删除这个id的学员.
    //3.1 先从学生库中读取出所有的学员
    const stus = require(jsonPath);
    //3.2 循环数组,判断数组中是否有一个学员的id刚好等于传过来的id
    let findIndex = -1;
    for (let i = 0; i < stus.length; i++) {
        if (stus[i].id == id) {
            //将当前遍历出来的这个学员从数组中删除.
            findIndex = i;
            break;
        }
    }
    //这个是在文件内的JSON数据读取和查找,效率相对比较低,在学习MySQL后可以进一步精简
    //循环结束以后,如果findIndex的值是-1 说明id不存在.
    if (findIndex == -1) return res.status(404).send({ code: 404, msg: 'id不存在' });
    // 说明id存在.
    //  先从数组中将这个元素删除.
    stus.splice(findIndex, 1);
    // 这个删除只是删除了内存中的数组中的元素. json文件中的数据是不会变的.
    //  将stus数组的数据重新写入到json文件中.
    fs.writeFile(path.join(__dirname, jsonPath), JSON.stringify(stus), 'utf-8', err => {
        if (err) return res.status(500).send({ code: 500, msg: err });
        res.send({ code: 200, msg: '删除成功' });
    });
}