Flandre923
3112 words
16 minutes
NodeJS简单操作

1.vscode 快捷操作#

ctrl+N 新建一个文件

ctrl+s 保存

ctrl+shift+p 打开命令面板

select default shell profile 更改默认的shell,默认是powershell

ctrl + ` 打开一个新的终端

ctrl + b 关闭侧边栏

2. 使用node运行js代码#

创建一个js文件为app,输入下面的代码

console.log("Hello world from  Node JS")

可以看到下面的运行结果

Hello world from Node JS

3. 模块#

一个js就是一个模块,负责一部分的功能,这样的分模块的设计可以减少耦合。

创建一个新的文件,使用module.exports暴露给外部使用的内容,函数,字段,或者类 tutorial.js

const sum = (num1,num2)=>num1 + num2;

module.exports = sum;

在app.js中导入这个方法

const tutorial = require("./tutorial")

console.log("Hello World From Node.js")
console.log(tutorial) // [Function: sum]
console.log(tutorial(1,2)) // 3

4. 如何导出更多的内容#

tutorial.js中输入下面的内容


const sum = (num1,num2)=>num1 + num2;
const PI =3.14;
class someMathObject{
    constructor(){
        console.log("objcet created");
    }
}

module.exports.sum = sum;
module.exports.PI = PI;
module.exports.someMathObject = someMathObject;

如何导入多这个内容

const tutorial = require("./tutorial")


console.log("Hello World From Node.js")
console.log(tutorial)
/*
{
  sum: [Function: sum],
  PI: 3.14,
  someMathObject: [class someMathObject]
}
*/
console.log(tutorial.sum(1,2)) // 3
console.log(tutorial.PI) // 3.14
console.log(new tutorial.someMathObject()) // someMathObject {}

一种更加简单的导出方式

const sum = (num1,num2)=>num1 + num2;
const PI =3.14;
class someMathObject{
    constructor(){
        console.log("objcet created");
    }
}

module.exports = {sum:sum,PI:PI,someMathObject:someMathObject}

5.node 事件模块#

定义事件,和回调函数,以及触发事件

const  EventEmitter = require('events'); // 导出事件监听器
const eventEmitter = new EventEmitter();// 创建事件监听器

eventEmitter.on("tutorial",()=>{//监听事件tutorial,第二个参数是回调函数
    console.log("tutorial event has occured");
});

eventEmitter.emit("tutorial"); // 发送一个事件tutorial

是否回调函数可以传入参数,当然是可以的。

const  EventEmitter = require('events'); // 导出事件监听器
const eventEmitter = new EventEmitter();// 创建事件监听器

eventEmitter.on("tutorial",(num1,num2)=>{//监听事件tutorial,第二个参数是回调函数
    console.log("tutorial event has occured");
    console.log(num1+num2)
});

eventEmitter.emit("tutorial",1,2); // 发送一个事件tutorial,并传入参数

我们可以同类继承的方式获得自己的事件类,添加额外的属性和方法,

class Person extends EventEmitter{// 定义了一个类,该类继承于EventEmitter
    constructor(name){
        super();
        this._name = name 
    }

    get name(){
        return this._name 
    }

}

const jack = new Person("jack")
jack.on("name",()=>{
    console.log("my name is "+jack.name)
})

jack.emit("name")

6. readLine#

我们来做一个简单的猜数小游戏,输入两数相加之后数值,然后你给出他们的计算之和,如果算错乐会提示你错误,然后从新输入。

const readline = require("readline")
const rl = readline.createInterface({ input: process.stdin, output: process.stdout })// 初始输入读取readline的对象,使用标准输入输出作为参数
let num1 = Math.floor((Math.random() * 10) + 1);
let num2 = Math.floor((Math.random() * 10) + 1);
let answer = num1 + num2

rl.question(`what is ${num1} + ${num2}? \n`, (userInput) => {
    if(userInput.trim() == answer){// == 回自动转型,判断将数值转为字符串然后比较
        rl.close(); // 如果回答对乐,我们将关闭rl
    }else{
         // 设置提示符
        rl.setPrompt("Incorrect response please try again !\n")
        // 提示
        rl.prompt()
        // 监听line事件,添加一个回调函数
        rl.on("line",(userInput)=>{ // 判断是否正确,不正确就继续提示玩家
            if(userInput.trim()==answer){
                rl.close();
            }else{
                rl.setPrompt(`Your answer of ${userInput} is incorrect \n`);
                rl.prompt()
            }
        })
    }
});

rl.on("close", () => {//监听close事件,如果close说明回答正确
    console.log("Correct!!")
});

7. 文件系统#

文件系统可以让你操作本地的文件和文件目录

如何写出一个文件

const fs = require('fs');

fs.writeFile("example.txt","this is an example",err=>{// 写出的路径和文件名,写出的内容,错误的处理
    if(err){
        console.log(err);
    }else{
        console.log("file written successfully");

    }
})

读取一个文件

const fs = require('fs');

fs.writeFile("example.txt","this is an example",err=>{//向指定的文件路径写入第二个参数的内容
    if(err){
        console.log(err);
    }else{
        console.log("file written successfully");
        fs.readFile('example.txt',(err,file)=>{ // 读取一个文件,第一个参数是文件的路径,第二个参数是回调函数
           // 回调函数中的第一个是错误,第二个是读取的文件内容,file是二进制数据 
            if(err){
                console.log(err)
            }else{
                console.log(file) // <Buffer 74 68 69 73 20 69 73 20 61 6e 20 65 78 61 6d 70 6c 65>  Buffer 读入的是一个二进制数据
            }
        })
    }
})

有没有什么方法指定读入的文件的按照字符的形式读入,可以的, 我们可以在读入的方法中指定读入的方法是utf-8

const fs = require('fs');

fs.writeFile("example.txt","this is an example",err=>{//向指定的文件路径写入第二个参数的内容
    if(err){
        console.log(err);
    }else{
        console.log("file written successfully");
        fs.readFile('example.txt','utf-8',(err,file)=>{ // 读取一个文件,第一个参数是文件的路径,第二个指定utf-8编码的方式读取,第三个参数是回调函数
            if(err){
                console.log(err)
            }else{
                console.log(file) // this is an example
            }
        })
    }
})

其他的一些功能


const fs = require('fs');


// 重命名一个文件

fs.rename("example.txt","example2.txt",err=>{
    if(err) {
        console.log(err);
    }else{
        console.log("success");
    }
});

// 向一个文件的末尾追加新的内容

fs.appendFile('example2.txt','some data being appended',(err)=>{
    if(err){
        console.log(err)
    }else{
        console.log("successfully append")
    }
});

// 删除一个文件

fs.unlink("example2.txt",(err)=>{
    if(err){
        console.log(err);
    }else{
        console.log("successfully delete");
    }
})

如何使用fs操作文件目录


// 创建一个目录
fs.mkdir("tutorial",(err)=>{
    if(err){
        console.log(err)
    }else{
        console.log("folder successfully created!")
    }
})

// 删除
fs.rmdir("tutorial",(err)=>{
    if(err){
        console.log(err)
    }else{
        console.log("folder successfully deleted!")
    }
})

// rmdir只能删除空文件夹,如何删除一个带有子文件的文件夹呢,首先获得文件夹下的所有文件,删除所有文件后在删除文件夹

fs.readdir("example",(err,files)=>{
    if(err){
        console.log(err);
    }else{
        for(file in files){
            fs.unlink("./example" + file,(err)=>{
                if(err){
                    console.log(err);
                }else{
                    console.log("success!")
                }
            });
        }
    }
})

8.写入流和写出流#

使用流读入文件可以将一个大文件分为很多小分读取,减少乐加载时间。


const fs = require('fs');

const readStream = fs.ReadStream('./example.txt',"utf8");//创建流
const writeStream = fs.WriteStream('./example2.txt');
readStream.on('data',(chuck)=>{//每次读取数据时候回发送data的回调事件
    writeStream.write(chuck);//写出流,将读入的内容写出到对应的文件,这样的方式能减少内存的使用。
})

// 一种更加简单的写法
readStream.pipe(WriteStream)

使用管道和压缩模块实现压缩和解压

const fs = require('fs');
const zlib = require('zlib');
const gzip = zlib.createGzip();


const readStream = fs.ReadStream('./example.txt',"utf8");//创建流
const writeStream = fs.WriteStream('./example2.txt.gz');

// 压缩
readStream.pipe(gzip).pipe(writeStream);

// 解压
const fs = require('fs');
const zlib = require('zlib');
const gunzip = zlib.createGunzip();


const readStream = fs.ReadStream('./example.txt.gz');//创建流
const writeStream = fs.WriteStream('./example2.txt');

readStream.pipe(gunzip).pipe(writeStream);

9. http#

Http模块可以让你创建一个http服务器,

const http = require("http")
const server = http.createServer((req,res)=>{ // 处理请求
    res.write("hello world from node js");//响应
    res.end(); // 结束
});

server.listen('3000'); // 监听端口

输入上述的内容之后,你可以在浏览器中输入对于的地址,显示你写的内容。

下面我们来看怎么处理路由

const http = require("http")
const server = http.createServer((req,res)=>{ // 处理请求
    if(req.url === '/'){// 处理/路由
        res.write("hello world from node js web server")
        res.end()
    }else{//如果是其他的路由就另外处理例如/asd 
        res.write('using some other domian')
        res.end()        
    }
});

server.listen('3000'); // 监听端口

10 托管静态资源#

就是你给http服务器发送请求,给你返回对应的文件内容

我们准备了一个static的目录,其中存放了一个html文件,一个exapmle.png的图片,和一个example.json的文件

首先显示如何将html显示在浏览器的页面上

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

http.createServer((req,res)=>{
    const readStream = fs.createReadStream('./static/index.html');
    res.writeHead(200,{"Content-type":"text/html"}); // 设置返回头,200表示请求成功,返回的内容是html格式
    readStream.pipe(res);// res是输入流,所以可以直接使用pipe
}).on(3000);

另外我们来看怎么发送json

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

http.createServer((req,res)=>{
    const readStream = fs.createReadStream('./static/example.json');
    res.writeHead(200,{"Content-type":"application/json"}); // 设置返回头,200表示请求成功,返回的内容是html格式
    readStream.pipe(res);// res是输入流,所以可以直接使用pipe
}).on(3000);

以及图片

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

http.createServer((req,res)=>{
    const readStream = fs.createReadStream('./static/example.png');
    res.writeHead(200,{"Content-type":"image/png"}); // 设置返回头,200表示请求成功,返回的内容是html格式
    readStream.pipe(res);// res是输入流,所以可以直接使用pipe
}).on(3000);

11. package.json以及npm的介绍#

package.json是一个重要的文件,包含了项目的版本号,名称,等等内容,

使用

  • npm init 初始化一个项目
    • 这里面会有很多提示内容
      • 例如 项目的名称
      • 版本
      • 描述
      • 项目的入口文件
      • 测试命令
      • git仓库
      • 关键词
      • 作者
      • 协议

对应一个初始化的项目,我们可以使用npm安装第三方的依赖包

npmjs.com 是一个网站,在这个网站上你可以找到各种软件包,在这里你可以找你需要的包

安装

  • npm install 包名字 安装成功之后,你可以在package.json中看到对应的依赖包,文件的目录下回多一个node_modules文件夹,你会发现你的安装包会在该文件夹下
{
  "name": "js",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "lodash": "^4.17.21"
  }
}

如何使用安装库

const _ = require('lodash')

let example = _.fill([1,2,3,4,5],"apple",1,4);
console.log(example)
// $ node app.js 
// [ 1, 'apple', 'apple', 'apple', 5 ]

删除软件包

  • npm uninstall 软件包名称

12 语义化#


  "dependencies": {
    "lodash": "^4.17.21"
  }
  // major.minor.patch 版本信息
  // patch主要是更新bug
  // minor 次要版本更新,添加一定的新功能,非破坏性更新
  // major 主要版本更新,破坏更新,可能两个版本不兼容
  // ^是指可以接受的版本是4.x.z版本,对minor更新版本和patch不做限制
  
  "dependencies": {
    "lodash": "~4.17.21"
  }
  // ~是指可以接受的版本是4.17.x版本,对patch版本不做限制
  // 如果没有符号
  
  "dependencies": {
    "lodash": "4.17.21"
  }
  //  指定必须是改版本

13. express 服务器框架#

express是一个基于Node的web服务器框架,之前使用http和fs建立一个web服务器,但是express更加强大,更加健壮

npm init —yes

全选默认配置 通过—yes来设置。

npm install express 安装 express

写一个hello world

const  express = require('express');
const app = express();
 
app.get('/',(req,res)=>{ // 接受/请求
    res.send("Hello world"); // 返回hello world
});

app.listen(3000);

14.http get请求#

传入参数

const  express = require('express');
const app = express();
 
app.get('/',(req,res)=>{ // 接受/请求
    res.send("Hello world"); // 返回hello world
});

app.get('/example',(req,res)=>{ // 添加一个新的路由请求/example
    res.send("hitting example route") // 返回一个字符串
});

// 如何可以获得前端发送的参数

app.get("/example/:name/:age",(req,res)=>{ // 请求路径:http://localhost:3000/example/zhangsan/13
    console.log(req.params) // 获得的内容{ name: 'zhangsan', age: '13' }
    // 
    res.send(req.params.name + " : " + req.params.age); //将获得数据返回回去。
    // query 传入数据 xxx?tutorial=xxxxx
    // 多个参数 xxx?name=xiaoming&age=3
    console.log(req.query)//{ tutorial: 'xxxxx' }
});

app.listen(3000);

15. 托管静态文件#

const express = require('express');
const path = require('path');

const app = express();

app.use("/public",express.static(path.join(__dirname,'static'))); // 有时候我们不想外部知道服务器的文件目录结构,通过这样的方式将static映射到public下

app.get('/',(req,res)=>{
    res.sendFile(path.join(__dirname,'static','index.html'))//返回static下面的index.html文件作为页面
})
app.listen(3000)

16 处理post请求#

npm install body-parser 我们要处理POST请求需要线安装这个库。

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();

app.use("/public",express.static(path.join(__dirname,'static')));
app.use(bodyParser.urlencoded({extended:false}));//使用中间件

app.get('/',(req,res)=>{
   res.sendFile(path.join(__dirname,'static','index.html'))
})

app.post('/',(req,res)=>{
   // 打印post请求的消息
   console.log(req.body);// 这里可以拿到消息
   //
   res.send("successfully posted data");
})
app.listen(3000)

17 使用body-parser解析json数据#

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();

app.use("/public",express.static(path.join(__dirname,'static')));
app.use(bodyParser.urlencoded({extended:false}));//使用中间件
app.use(bodyParser.json()); // 使用body-parser解析json


app.get('/',(req,res)=>{
    res.sendFile(path.join(__dirname,'static','index.html'))
})

app.post('/',(req,res)=>{
    // 打印post请求的消息
    console.log(req.body);// 这里可以拿到消息
    //
    res.json({success:true}) // 返回一个json
})
app.listen(3000)

18.用户验证逻辑#

使用@hapi/joi 实现验证用户的逻辑

npm install @hapi/joi

const express = require('express');
const path = require('path');
const Joi = require('@hapi/joi');
const bodyParser = require('body-parser');
const app = express();

app.use("/public",express.static(path.join(__dirname,'static')));
app.use(bodyParser.urlencoded({extended:false}));//使用中间件
app.use(bodyParser.json()); // 使用body-parser解析json


app.get('/',(req,res)=>{
    res.sendFile(path.join(__dirname,'static','index.html'))
})

app.post('/',(req,res)=>{
    // 打印post请求的消息
    console.log(req.body);// 这里可以拿到消息
    //
    const schema = Joi.object().keys({ // 使用Joi创建对输入的验证
        email:Joi.string().trim().email().required(),// email 要求字符串无空格,邮箱格式,不能传空
        password:Joi.string().min(5).max(10).required() // passworld,最少5字符,最多10字符,不能穿空
    });
    Joi.validate(req.body,schema,(err,value)=>{ 
        if(err){
            console.log(err);
            res.send("an error has occurred");
        }
        console.log(value);
        res.send("successfully posted data");
    });
    res.json({success:true}) // 返回一个json
})
app.listen(3000)

19.ESJ 模板#

EJS 是一个简单的模板引擎,使用它我们可以在html中嵌入js代码

const express = require('express');
const path = require('path');
const app = express();

app.use("/public",express.static(path.join(__dirname,'static')));
app.set('view engine','ejs');

app.get('/:userQuery',(req,res)=>{ // 传参,将将ejs解析为html然后返回
    res.render('index',{data:{userQuery:req.params.userQuery}});
})

// app.get('/', (req, res) => { // 将将ejs解析为html然后返回
//     res.render('index');
// })

app.listen(3000)

19 中间件就是函数#

之前讲解了一个bodyparser的中间件,现在来看下中间怎么自己写。

const express = require('express');
const app = express();
app.use((req,res,next)=>{ // 中间件会先于路由执行
    console.log(req.url,req.method);
    next(); //必须调用,传递这个请求,不然服务器没有处理完这个请求,也不会有返回信息给客户端,知道超市中断连接
});

app.use('/example',(req,res,next)=>{
    // 只有包含了example的路由回使用该中间件
    next();
})
app.listen(3000)

20 一般的模块化方法#

routes/people.js

const express = require('express');
const route = express.Router();

route.get('/',(req,res)=>{
    res.send("/ bing hit ");
})


route.get('/example',(req,res)=>{
    res.send('/example being hit')
});

module.exports = route;

app.js

const express = require('express');
const path = require('path');
const app = express();
app.use('/public',express.static(path.join(__dirname)));
app.set('view engine','ejs')
const people = require('./routes/people')
app.use('/people',people)
app.listen(3000)

/people -> / binging hits /people/example -> /example being hit

NodeJS简单操作
https://fuwari.vercel.app/posts/study/node/
Author
Flandre923
Published at
2024-07-27