Nodejs 学习笔记

news2024/9/28 1:06:16

Author:@德玛玩前端
Date: 2023-07-06

Nodejs

一、Nodejs概述

1.1、什么是JavaScript

1995年由Netscape公司退出,后经ECMA统一标准的脚本语言。通常狭义上理解的JS是指在浏览器内置的JS解释器中运行的,主要用途是操作网页内容,实现用户交互

1.2、什么是Nodejs

2009年由Ryan Dahl开发,现由Nodejs Foundatuin维护,基于Google V8引擎的JS运行时环境,其运行完全脱离浏览器,可以编写独立的服务器端程序,主要用途为文件读写,网络访问,加密压缩,数据库操作等。

官网网站:www.nodejs.org
中文镜像网站:www.nodejs.cn

1.3 Javascript 和 Nodejs的区别

  • 使js既可以编写客户端应用,又可以编写服务端应用了。一种语法统一前后端。
  • 区别
    • js属于客户端技术,运行在浏览器。nodejs是服务端技术,与PHP、JSP等是类似的技术
    • js有多种解释器可以使用,如ie的chakra,ff的猴子系列,chrome的v8等等,nodejs运行于基于v8引擎改进而来的运行时环境
    • js因为解释器有多种,所有存在代码兼容性问题,nodejs只有一种解释器,所以不存在代码兼容性问题。
    • js 对象包括:ES原生对象,用户自定义独象,宿主对象(例如 DOM & BOM对象);nodejs 对象包括:ES原生对象,用户自定义对象,Nodejs扩展对象。
    • js主要用于网页DOM元素的操作,实现用户交互效果,主要用于实现服务器端进行逻辑,如文件系统操作,数据库访问,其他服务器调用等。

二、安装和检测

  • 安装步骤 【nodejs官方有安装说明支持】

  • 安装后检测是否安装完成

    • widow + R
    • 输入"cmd"
    • node -v 查看当前nodejs的版本号
    • npm -v 附带的安装工具,查看版本号可检测node是否安装完成
  • 进入交互模式

    • node + 回车 进入交互模式
    • ctrl+c 两次 / exit 退出交互模式
  • 交互模式和脚本模式的区别

    • 交互模式(REPL模式 Read-Evaluate-Print-Loop )
      • 读取用户输入,执行运算,输出执行结果,继续下一次循环
      • 交互模式下,Nodejs自带的模块无需引入
    • 脚本模式
      • 将所有语句编写在独立的脚本文件中,一次性执行
      • 脚本模式下,除了全局对象以其相关成员外,所有其他模块中声明的对象和方法必须使用require引入

三、Nodejs的体系结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c8Gnbcum-1688651272348)(https://note.youdao.com/yws/res/28788/WEBRESOURCEc3c34b09e63df2beb941dbaf9d58b67a)]

四、Node.js的语法

  • Nodejs语法是基于JavaScript的。下列内容与JS是完全一样的

    • 数据类型
    • 声明变量和常量
    • 运算符
    • 逻辑结构
    • 函数作用域和闭包
    • 对象和原型
    • 对象分类
  • Nodejs的数据类型

    • 原始类型(Primitive Type)

      • string、number、boolean、null、undefined
    • 引用类型 (Reference Type)

      • ES核心对象 Global String Number Boolean Date Math Ar
        ray Error Function Object RegExp
      • Nodejs对象:Buffer ReadStream ClientRequest
      • 自定义对象

五、Node.js的特点

  • 简单,避免过渡设计
  • 单线程逻辑处理
  • 非阻塞的异步I/O处理
  • 事件驱动编程
  • 无锁机制,不会产生死锁
  • 支持数万个并发连接 (承载访问量大,腾讯使用)
  • Node.js适合搭建以IO操作为主,响应速度快,易于扩展的网络应用,例如
    • 命令行工具
    • 带有GUI界面的本地应用程序
    • 交互式终端程序
    • 基于社交网络的大规模web应用
    • web socket服务器
    • TCP/UDP套接字程序
    • 客户端javascript编译器
  • Nodejs不适合CPU密集型应用
    • 深层次的嵌套和递归
    • 复杂加密和解密算法
    • 高可靠性运算
    • 严格内存管理
    • 数据挖掘和数据分析

六、Nodejs对象

6.1、global 全局对象

  • 详见官网 https://nodejs.org/dist/latest-v14.x/docs/api/globals.html#globals_console

  • 在交互模式下,声明的变量和创建的函数都是global下的,例如global.a global.fn()

  • 在脚本模式下,声明的变量和创建的函数都不是global下的

    // global.fn is not function 
    
  • 但是,在js下,声明的变量和创建的函数都是在全局window下,例如window.a、window.fn()

6.2、console对象

  • console.log() 打印日志

  • console.info() 打印消息

  • console.warn() 打印警告

  • console.error() 打印错误

  • console.time() 开始计时

  • console.timeEnd() 结束计时 //开始计时和结束计时的字符串要保持一致

    console.log(1); 
    console.info(2);
    console.warn(3);
    console.error(4);//浏览器下看,nodejs下看不出区别
    
    console.time('for')
    for(let i=1;i<10000;i++){
      //.....
    }
    console.timeEnd('for')
    
    
  • 小案例:查看相同情况下,for while do-while 哪一个更快

    console.time('for')
    for(let i=1;i<=10000;1++){
    
    }
    console.timeEnd('for')
    
    console.time('while')
    let i=1;//let 不能反复的声明变量
    while(i<=10000){
       i++
    }
    console.timeEnd('while')
    
    console.time('do-while')
     i=1;
     do{
        i++
     }while(i<=10000)
    console.timeEnd('do-while')
    
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RkX1ELjA-1688651272350)(https://note.youdao.com/yws/res/28759/WEBRESOURCE2ccde4844eef8adad5e809460ff51d3c)]

6.3、process 进程对象

交互模式下使用

process.arch 查看当前cpu的架构

process.platform 查看当前的操作系统

process.version 查看当前的操作系统

process.env 查看当前计算机的环境变量有哪些

process.kill() 结束某个编号的进程

process.pid 查看当前进程的编号

6.4、Buffer对象

缓冲区:在内存中临时存储数据的区域,常用于网络传输时的资源,程序结束就消失。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lrc7o86c-1688651272351)(https://note.youdao.com/yws/res/28761/WEBRESOURCEcd67a09e51cf287c07d094ab07c5aaa0)]

//创建buffer
let buf=Buffer.allow(6,'23a22d')// 6个字符,存储的数据
//Buffer数据使用时需要转字符串
console.log(buf.tostring())//获取的buffer数据(unicode码)转字符串
//console.log(string(buf))

6.5、timer 定时器 (全局函数)

  • setTimeout(callback,delay) / clearTimeout(tiemr) 一次定时器

  • setInterval(callback,delay) / clearInterval(tiemr) 周期定时器

  • setImmediate(callback) / clearImmediate(tiemr) 立即执行器

  • process.nextTick(callback)

    
    console.log(2)
    setImmediate(()=>{
      console.log(1)
    })
    process.nextTick(()=>{
      console.log(4)
    }) //process.nexTick中的回调函数会放在主线程的最后
    
    console.log(3)
    
    // 2 3 4 1
    
    

七、模块系统

  • 模块:就是一个独立的功能体

  • 分为3类:自定义模块,核心模块,第三方模块

  • Nodejs下规定,以一个文件就是一个模块,模块中的每一个变量和函数不能被web访问,模块中的代码被一个构造函数所包含,模块外部无法得到。

     (function(exports,require,module,__filename,__dirname){
          //代码 .............
     }) 
    
  • 引入模块往往用常量保存,常量名称通常就是模块的名字。

7.1、require()

用于引入另一个模块(对象)属性以及内容,同一级必须添加./,后缀名可以省略。

7.2、exports

如果导出的对象为空,可以往对象中添加导出的内容。

案例:

创建两个模块,主模块main.js和功能模块circle.js,在功能模块下创建两个函数,传递半径计周长和面积,导出这两个函数;在主模块下引入,并调用两个函数。


//main.js
const circle=requrie('./circle.js') //引入一个模块默认都是对象
//console.log(circle)
console.log(circle.getArea(5).toFixed(2))
console.log(circle.getLength(5).toFixed(2))
console.log(circle.add(2,3))//5

//circle.js
function getArea(r){
   return Math.PI*Math.pow(r,2)
}

function getLength(r){
   return Math.PI*2*r
}

export.getArea=getArea
export.getLength=getLength //添加导出对象
exports.add=(a,b)=>a+b;
//exports={} 

7.3、module

当前的模块对象

module.exports 当前模块要导出的对象

exports 导出对象的别名,等价于modules.exports

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yTPwr0fG-1688651272352)(https://note.youdao.com/yws/res/28766/WEBRESOURCE82a59dd47b969c2cb9f8dff117edf095)]


//都可以添加
exports.a=1
mpdules.exports.b=3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XWAA52oL-1688651272353)(https://note.youdao.com/yws/res/28768/WEBRESOURCE28786644ec8ea4584eb89211e44787cb)]


// 用一个新的对象作为导出对象
module.exports=emp
console.log(exports===module.exports) //false

7.4、__filename

当前模块的绝对路径+模块名称(文件名)

7.5、__dirname

当前模块的绝对路径 directory

7.6、require() 模块的引入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OlX9ffUk-1688651272354)(https://note.youdao.com/yws/res/28770/WEBRESOURCE0d6f03146bcacbd4d44181407d33dc3f)]

  • 自定义模块

    • require('./cicrle.js') // 路径方式引入js文件

    • require('./circle') // 路径方式引入js文件,后缀名可以省略

    • require('./dir') // 模块方式引入,需要初始化文件package.json, 优先引入文件中main属性对应的文件名,默认是index.js

  • 第三方模块

    • 使用前提:npm下载到node_modules
    • require(‘mysql’) 默认引入index.js
  • 核心模块

    • require(‘fs’)
    • 直接引用 nodejs官网提供

八、核心模块(官方提供的内置模块)

8.1、querystring模块–查询字符串

查询字符串是什么?传递数据

浏览器向web服务器发送请求,传递数据的一种方式,位于URL中间号后的部分
http://www.baidu.com/list.html?username="dema" & age=22'

包含的api:

parse() 将查询字符串解析为对象

stringify() 将对象格式化为查询字符串


// 引入查询字符串模块
const qs=require('querystring') //自动从官方下载
let str="kw=dell&price=4999"
// 查询字符串解析为对象
let obj=qs.parse(str)
console.log(obj)

//将对象格式化为查询字符串
let obj2={
   lid:18,
   title:'dell'
}
let str2=qs.stringify(obj2)
console.log(str2) //lid=18&title=dell


8.2、URL模块–处理和解析URL

包含的Api:

parse()解析url为对象后,从而可以获得url中的任意部分

format() 将对象格式化为url,对象的字符串部分放的是对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GykNLXdu-1688651272355)(https://note.youdao.com/yws/res/28772/WEBRESOURCEbc257327ca2269db00b943a799010e60)]

console.log(url.parse(str))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g55JksN2-1688651272356)(https://note.youdao.com/yws/res/28774/WEBRESOURCE65f7025cef24a73c4474a16cc745e652)]

小案例:获取url中查询字符串的value值


// 思路
// 1. 引用url模块,将url转化成对象,拿到query的字符串
// 2. 引用querystring模块,先将query字符串转换成对象,在获取里面的value值

const url=require('url')
const qs=require('querystring')

let str="https://baidu.com/web/1.html?username='dema'&age=22"

let obj=url.parse(str)

let obj2=qs.parse(obj.query)

console.log('username',obj2.username,'age',obj2.age)
//username 'dema' age 22 


8.3、fs 文件系统模块

8.3.1、查看是否为文件

  • fs.isFile()

    • 返回 ture 或 false

8.3.2、查看是否为目录

  • fs.isDirectory()

    • 返回true或false

8.3.3 查看文件状态

  • fs.stat(path,callback) 异步获取

    • 这个api的获取通过callback,而不是通过返回值

    • path 文件的路径

    • callback 回调函数,用于获取结果

    • err 可能产生的结果

    • result 文件的结果状态

      
      const fs=require('fs')
      //通过回调函数的第二个参数来打印结果
      let res=fs.stat('homework.js',(err,result)=>{
           if(err) throw err //抛出代码,组织代码向后运行
           console.log(result) // result为局部作用域
      })
      
      
  • fs.statSync(path) 同步获取

    • 这个api结果的获取直接通过返回值

    • path 文件的路径

      const fs=require('fs')
      let result=fs.statSync('homework.js')
      console.log(result)
      

8.3.4 创建目录

  • fs.mkdir(path,callback) 异步创建

    
     const fs=require('fs')
     fs.mkdir('mkdir',(err)=>{
         if(err) throw err;
         console.log('目录创建成功')
     }) // 线程池的 结果放进事件队列
     console.log('end') //主程序的
     // 执行结果: end   目录创建成功
    
    
  • fs.mkdirSync(path) 同步创建

    const fs=require('fs')
    fs.mkdirSync('mkdir')//同步也是主程序
    consoel.log('end')//主程序
    // 执行结果: 先创建文件夹,再输出 end 
    

8.3.5 移除目录

如果目录中有文件要先删除文件

  • fs.rmdir(path,callback) 异步删除

     const fs=require('fs')
     fs.rmdir('mydir',(err)=>{
        if(err) throw err
        console.log('移除成功')
     })
    
  • fs.rmdirSync(path) 同步删除

    cosnt fs=require('fs')
    fs.rmdirSync('mydir')
    

8.3.6、读取目录

读取到的目录里的文件以数组的形式呈现

  • fs.readdir(path,callback) 异步读取目录

     const fs=require('fs')
     fs.readdir('mkdir',(err,result)=>{
         if(err) throw err
         console.log(result)
     })
    
  • fs.readdirSync(path) 同步读取目录

     const fs=require('fs')
     let result=fs.readdirSync('mkdir')
     console.log(result)
    

8.3.7、创建文件并写入

  • fs.writeFile(path,data,callback) / fs.writeFileSync(path,data)

    • 创建文件和写入文件同一个api,因为写入的文件没有就是创建,如果文件有并且有数据,直接清空,然后写入新数据
    • path 文件的路径
    • data 写入的数据
    
    const fs=require('fs')
    // 异步创建
    fs.writeFile('1.txt','redu.cn',(err)=>{
         if(err) throw err
         console.log('文件写入成功')
    }) 
    
    //同步创建
    fs.writeFileSync('2.txt','hello')
    
    
  • fs.appendFile(path,data,callback) / fs.appendFileSync(path,data)

    • 如果文件不存在,先创建然后写入
    • 如果文件存在,在文件的末尾追加写入
    
    const fs=require('fs')
    //异步创建
     fs.appendFile('1.txt','hello',(err)={
         if(err) throw err
         console.log('追击使用成功')
     })
    
    //同步创建
     fs.appendFileSync('2.txt','hello')
    
    
  • 案例:使用同步创建文件的方法将后台获取的json数据写入文件’student.txt’中

    
    const fs=require('fs')
    var arr=[
       {eid:1,ename:'huwenhao',sex:1}
       {eid:2,ename:'king',sex:2}
       {eid:3,ename:'kawb',sex:0}
    ]
    
    for(var val of arr){
        let str='序号'+val.eid+'姓名'+val.ename+'性别'+val.sex
        fs.appendFileSync('student.txt',str)
    }
    

8.3.8、读取文件

  • fs.readFile(path,callback) 异步读取

  • fs.readFileSync(path) 同步读取

    
     const fs=require('fs')
     //异步读取
     fs.readFile('student.txt','utf-8',(err,data)=>{
         if (err) throw err
         console.log(data)
     })
     //同步读取
     let data=fs.readFileSync('3.txt')
     console.log(data.toString())
    
    

8.3.9、删除文件

  • fs.unlink(path,callback) 异步删除

  • fs.unlinkSync(path) 同步删除

    
    const fs=require('fs')
    // 异步删除
    fs.unlink('2.txt',(err)=>{
        if(err) throw err
        console.log('删除成功')
    })
    
    // 同步删除
    fs.unlinkSync('2.txt')
    
    

8.3.10、检测文件或文件夹是否存在

  • 异步已废除,只有同步方法

  • fs.existsSync(path) 返回true和false,可做条件表达式

    
    const fs=require('fs')
    if(fs.existsSync('3.txt')){
      fs.unlinkSync('3.txt')
      console.log('已经被删除')
    }else{
       console.log('3.txt不存在')
    }
      
    

8.3.11、读取流

读取文件的方式,是先把数据存入内存中,然后再从内存中获取数据,如果读取的文件太大,会造成内存压力过大,所以就有了流的操作。分段放入内存,再把数据从内存中取出。

各种类型的数据,例如压缩包,txt,word等

压缩包里不是文本文档,转换为字符串会造成卡死

流读取大型文件,会分成几段读取,所以读取速度快


const fs=require('fs')
// 创建一个可读取的流
let readStream=fs.createReadStream('jj.txt')
// 事件:监听是否有数据流入内存
// data: 事件名称,监听数据的事件
// 通过回调函数来获取数据
let count=0
readStream.on('data',(chunk)=>{
  // chunk就是获取的数据,要转成字符串
  // console.log(chunk)
  // console.log(chunk.toString())
  count++ // 当文件大需要分段读取的时候,每度一段加1
})
// 读取结束的事件
readStream.on('end',()=>{
  console.log(count)
})

8.3.12、写入的流

把读取的文件放入另一个文件里,最终实现拷贝效果适用于较大文件提高性能


const fs=require('fs')
// 创建可读取的流
let readStream=fs.createReadStream('jj.txt')
// 创建可写入的流
let writeStream=fs.createWriteStream('database.txt')
// 把读取的流通过管道添加到写入流 拷贝
readStream.pipe(writeStream)

8.3.13、普通小文件copy

  • fs.copyFile(src,dest,callback) 异步拷贝
  • fs.copyFileSync(src,dest) 同步拷贝

// 拷贝小文件 例如微信传递一个文件也是copy的过程
const fs=require('fs')
fs.copyFile('jj.txt','jj2.txt')

8.4、http模块

  • 模拟浏览器向另外的服务器发请求

    • http.get(url,callback) 向服务器发请求,通过回调函数获取结果

      • url 请求得URL
      • callback 回调函数,获取结果
        const http=require('http')
        http.get('www.baidu.com',(res)=>{
           res.on('data',(chunk)=>{
              consle.log(chunk.toString())
           })
        })
        
    • http模块发送get请求

      • 导入http模块

        var http = require('http');
        
      • 配置请求对象(请求方式,url,请求路径)

        var options = {
            host: 'http://dema.com',
            port: 10077,
            method: 'GET',
            path: '/dema.txt',
            headers: {
                'Content-Type': 'text/plain'
            }
        }
        
      • http.request(地址,响应结果) 发送请求

         //发送请求
         var req=http.request(options.function(res){
            let info=""
            //通过监听res的data事件,可以得到返回的结果
            //返回的结果是一点一点拼接的,不是一次性接收完毕
            res.on('data',function(chunk){
                info+=chunk.toString()
            })
            //监听data,数据什么时间接收完毕
            res.on('end',function(err){
                console.log(info)
            })
        
         })
        
         req.end()
        
    • http模块发送post请求

      • 导入http模块

         var http = require('http');
         //POST多了一个请求参数的处理
         var querystring = require('querystring');
        
      • 配置请求对象(请求方式,url,请求路径)

         //参数的处理
         var data=querystring.stringify({
            name:'zhangsan',
            age:20
         })
        
         //请求对象的设置
         let options={
           host:'www.dema.com',
           port:10077,
           method:'POST',
           path:'/2.txt',
           headers: {
          'Content-Type': 'application/x-www-form-urlencode',
          //必须在请求头中设置内容的长度
          'Content-Length': Buffer.byteLength(data)
           }
         }
        
        
      • http.request(地址,响应结果) 发送请求

         var req = http.request(option, (res) => {
            let info = ''
            //post请求返回的结果是一个BUffer类型的数据,需要转化
            res.on('data', (chunk) => {
                info += chunk.toString();
        
            })
            res.on('end', (err) => {
                console.log(info);
                console.log(err);
            })
         })
         req.write(data) //把请求数据放在请求体里面
         req.end()
        
  • 创建web服务器

    • http.createServer() 创建web服务器

      
       let app=http.createServer();
       app.listen(8080) //监听端口
       // 监听浏览器请求,并通过回调函数获取请求,以及做出响应
       app.on('request',(req,res)=>{
          
            //res 响应对象
            //res.writeHead() 设置响应的状态码和头信息
            //res.write() 设置响应的内容
            //res.end() 结束并发送响应到客户端
               
                // 返回响应的内容
                res.write(' this is my first web')
                res.end()
      
                // 解决中文乱码
                res.writeHead(200.,{'Content-Type':'text/html;charset=utf-8'})
                res.write('')
                res.end()
      
                // 跳转到另一个url
                res.writeHead(302,{
                  Location:'http://baidu.com'
                })
                res.end()
      
            //req 请求的对象
            //req.url 请求的URL显示端口号后的部分,表示要获取的内容
            //req.method 请求的方法
            //req.headers请求的头信息
      
       })
      
      
    • get传递的数据容易被浏览器缓存(历史记录的url会显示请求的字符串数据)

    • 获取get请求的数据 (req.url)

      
      const url=require('url')
      const qs=require('querystring')
      var params = qs.parse(url.parse(req.url).query);
      
      
    • 获取post请求的数据 (req.on())

      事件:监听是否有数据传递,通过回调函数来获取数据

      
      req.on('data',(chunk)=>{
        // Chunk 就是传递的数据,格式是buffer,转为字符串后为查询字符串,需要解析为对象。
      })
      
      

九、第三方模块

9.1、包(目录模块)和npm

commonJS规范 nodejs往服务器发展的一种规范

nodejs是由多个模块组成,每个模块都有自己独立的作用域,变量和方法。一个模块的变量和方法在其他是不可见的,即使映入其他的模块,在web中也是不可见的,一个模块属于半封闭状态,需要导出后,另一个模块才能引入并看到此模块的方法。require,exports,exportsmodules都是由commonJS提出的。

包:就是一个目录模块

npm: 用于管理包的工具。www.npmjs.com 全局前端放包处,例如:Mysql express koa egg 都是创建web服务器、构建后台的框架。

9.2、搭建第三方模块的使用环境

  • cmd切换到指定目录下,npm init --y初始化生成package.json文件(项目包说明文件,会记录项目相关内容及包的信息),不加这个文件,不会下载到该位置

  • npm install express安装第三方模块,自动生成package-lock.json文件(记录依赖包的版本号)和node_modules文件夹(第三方模块的包和依赖包)。

  • npm install 自动安装package.json 和 package-lock.json中记录的包以及对应的版本号。

【注】 因为依赖的包太多,node_modules的文件包较大,所有实际工作中,将项目拷贝给别人或者别人将项目拷贝过来,理由并不会有这个文件包,但是会有package.json和package-lock.json文件,执行npm install就会自动安装node_modules的文件。

9.3、express框架

9.3.1、安装

  • 终端,cd到指定文件夹下
  • 准备文件,npm init -y生成文件package.json,不加这个文件,不会下载到该位置
  • 安装,npm install express,安装好后,会出现package-lock.json文件和node_modules文件夹。该文件下就会出现node_modules文件夹,里面是express的包和附带包。
  • 启服务
     const express=require('express')
     //创建web服务器
     let app=express()
     //监听端口
     app.listen(8080)
    

9.3.2、路由

每一个路由处理一个请求,并且都是独立的

app.Method(path,callback)

案例

  • 和 http相比,不需要考虑标签和编码问题, 只能用一次send()

    
    // 创建路由:根据请求的URL和方法做出响应
    // get 请求的方法 /login请求的url  callback做出的响应
    app.get('/login',(req,res)=>{
        //req请求的对象
        //res响应的对象
        res.send('<h2>德玛玩前端</h2>')//发送给客户端
    })
    
    
  • 响应发送文件

     
     app.get('/list',(req,res)=>{
        //响应文件
        res.sendFile(__dirname+'/list.html')
     })
    
    
  • 响应发生重定向

    
      app.get('/study',(req,res)=>{
        //跳转
        res.redirect('http://www.dema.com')
      })
    
    

9.3.3、响应对象和请求对象

  • res 响应的对象

    • res.send() 设置响应的内容并发送
    • res.sendFile() 响应文件并发送,文件需要使用绝对路径
    • res.redirect() 响应的重定向,跳转到另一个URL
    • 以上的方法只能执行一次,表示响应已经结束
  • req 请求的对象

    • req.url 获取请求的url
    • req.method 获取请求的方法
    • req.query 获取查询字符串数据,并解析为对象
    • req.params 获取路由传参的数据,格式为对象

9.3.4、获取get请求的数据

  • Get传递的数据容易被浏览器缓存(历史记录的url会显示请求的字符串数据)

  • 方式1:字符串传参

      // 获取查询字符串数据,并自动解析为对象
      cconsole.log(req.query)
      res.send('注册成功,用户名:'+req.query.uname)
    
  • 方式2:路由传参

      // 路由传参
      app.get('/pacckage/:pname',(req,res)=>{
          //获取路由传参的数据
          console.log(req.params.pname)
      })
    

9.3.5、获取post请求的数据

  • 方式一:同http模块接收方式,用事件监听

    • 事件:监听是否有数据传递,通过回调函数来获取数据

      req.on('data',(chunk)=>{
        // chunk 就是传递的数据,格式是buffer,转为字符串后为
      })
      
  • 方式二:安装express第三方中间件 body-parser(下方有详细解释)

9.3.6、express中间件

所有中间件的基础语法:app.use() (注:let app=express())

浏览器向服务器发请求,中间件可以拦截(过滤)请求,最终给路由提供服务的。

可分为:

  • 应用级中间件
  • 路由级中间件
  • 内置中间件
  • 第三方中间件 https://www.expressjs.com.cn/resources/middleware.html
  • 错误处理中间件

[注]:Expressjs 从4开始,只保留一个内置中间件,其他都作为第三方中间件使用。

应用级中间件

app.use(url,(req,res,next)=>{})

  • url:表示中间件要拦截哪一个路由,对应路由的url,如果为空表示拦截所有的请求
  • req res:在中间件中可以获取请求的对象,也可以做出响应
  • next是一个函数,表示执行执行下一个中间件和路由
     const express=require('express')
     let app=express()
     app.listen(8080)
    
     // 添加中间件,权限设置
     app.use('/list',function(req,res,next){
         if(req.query.uname!='root'){
            res.send('没有权限')
         }else{
            next() //下一个中间件或路由
         }
     })
     
     // 添加中间件,商品价格打9折
     app.use('/shopping',(req,res,next)=>{
         console.log(req.query)
         req.query.price*=0.9
         next()
     })
    
     //list接口
     app.get('/list',(req,res)=>{
         res.send('允许拿到数据....')
     }) 
    
     //shopping接口
     app.get('/shopping',(req,res)=>{
       res.send('商品价格为'+req.query.price)
     })
    
    
    

路由级中间件(路由器)

  • 主模块使用路由器:express().use(url,Router)

  • 模块中创建路由器:express.Router()

  • 管理各个模块的路由

  • 实际开发过程中,web服务器里不会再有路由,所有的路由都由路由器管理

  • 有多少功能模块,就有多少路由器

  • 实际开发项目中,按功能模块划分:(每一项都是一个路由)

    • 用户模块:注册 登录 我的收藏 个人中心 列表

    • 商品模块:首页 列表 详情

    • 购物车模块:添加 修改 删除

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Y5vG8FY-1688651272357)(https://note.youdao.com/yws/res/28777/WEBRESOURCE67a9cfcce9b334ffd4219c7e735785bc)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vCIFRHsr-1688651272358)(https://note.youdao.com/yws/res/28779/WEBRESOURCE7eef03c175a651d3d484e8b5d5335e15)]

内置中间件

  • app.use(express.static('public'))

  • 托管静态资源,把所有的静态资源托管到指定的目录,如果浏览请求文件,自动到该目录下寻找,不需要再创建路由响应文件res.sendFile()

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W9H26Weh-1688651272358)(https://note.youdao.com/yws/res/28782/WEBRESOURCE259f88fa31df5b9d0967bb76a9e9ce2f)]

    const express=require('express')
    const qs=require('querystring')
    let app=express()
    app.listen(8080)
    app.use(express.static('public'))
    
    app.post('/myLogin',(req,res)=>{
       req.on('data',(chunk)=>{
          let obj=qs.parse(chunk.toString())
          console.log(obj)
       })
       res.send('登录成功')
    })
    
    

第三方中间件(模块)

1.body-parser 可以转换数据类型

  • 安装: npm install body-parser

  • 因为安装express后node_modules已经存在此中间件,所以不需要安装,直接使用

    const express=require(express)
    const bodyParser=require('body-parser')
    cosnt qs=require('querystring')
    let app=express()
    app.listen(8080)
    
    //第三方中间件放在路由之前
    app.use(bodyParser.urlencoded({
       extended:false 
       //false 表示内部解析为对象不使用qs,true表示使用qs模块,内部自动完成不需要手动引入qs模块。
    }))
    
    // 创建对应的路由
    // 接收post请求的参数,取代监听请求数据的方法
    app.post('/myLogin',(req,res)=>{
       console.log(req.body)
       console.log(req.body.username)
       console.log(req.body.password)
        
    //   req.on('data',(chunk)=>{
    //      let obj=qs.parse(chunk.toString())
    //      console.log(obj)
    //   })
    })
    
    

2.compress 压缩

  • 安装 npm install compression

    const compression=require('compression')
    express().use(compression())
    
    // 使用方式1:
    // 可以用compression中间件压缩和处理静态内容。
    // 要在 express.static() 之前使用
    app.use(express.static(path.join(__dirname, 'public')));
    
    // 使用方式2:
    // 在路由之前使用,路由里的文件响应到browser进行了压缩
    app.get('/list',(req,res)=>{
      res.sendFile(__dirname+'/public/list.html')
    })
    
    

9.4、mysql模块 连接数据库

  • 安装 npm install mysql --save

  • 引入方式 const mysql=require('mysql')

  • 创建方式

    • mysql.createConnetion()
    • mysql.createPool() 线程池方式更高效
  • 占位符 :防止SQL注入,sql语句是用户输入的值

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KufcQcgg-1688651272359)(https://note.youdao.com/yws/res/28784/WEBRESOURCE092ec218202f2376a8c503a859792b98)]

  • 执行对数据库的增删改善

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NWhPBHeF-1688651272359)(https://note.youdao.com/yws/res/28786/WEBRESOURCE6dbc72fd24cfbce31208726bbe749937)]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/737798.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跨境电商亚马逊卖家为何要使用云服务器?

云服务器&#xff0c;作为跨境电商亚马逊开店必备的工具之一&#xff0c;深受各方卖家的青睐&#xff0c;由于跨境电商亚马逊平台有着一人一店的规定&#xff0c;但很多卖家朋友&#xff0c;为了获得更多的流量&#xff0c;便去开设多个店铺进行引流&#xff0c;这样操作极易诱…

【数据结构】搜索二叉树/map/set

二叉搜索树&#xff08;搜索二叉树&#xff09; 1.1.二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则…

【爆肝帝,花费3个月整理】金九银十面试季,2023年字节跳动所有,软件测试面试题拿走不谢!(附详细答案解析)

前言 最近有收到一些不同公司的面试题&#xff0c;像字节跳动、网易、美团等&#xff0c;趁着有时间&#xff0c;给大家梳理下&#xff0c;说不定面试能派上用场&#xff0c;大概给大家从以下几个方面来做了整理&#xff1a; 个人信息&#xff1a;(工作/实习经验&#xff0c;…

2023 ciscn 华东北分区赛 pwn minidb

2023 ciscn 华东北分区赛 pwn minidb 没去打比赛&#xff0c;做了一下&#xff0c;本地通了&#xff0c;不知道远程可不可以 结构体 00000000 Data struc ; (sizeof0x40, mappedto_8) 00000000 type dd ? 00000004 flag dd ? 00000008 database_name dq ? 00000010 pair d…

用html+javascript打造公文一键排版系统1:设计界面

近日&#xff0c;有同事抱怨收到的文件没有按公文要求进行排版&#xff0c;不得不自已动手帮他们擦PP排版&#xff0c;感慨每天都在做这些无意义的事情&#xff0c;浪费生命&#xff01; 于是打算用用htmljavascript打造公文一键排版系统。 首先是设置界面&#xff0c;主要包…

优化成本,探索WhatsApp API发送更经济的OTP验证信息

在现代的数字化世界中&#xff0c;安全性和使用者验证变得至关重要。随着移动应用程序和在线服务的普及&#xff0c;一次性密码&#xff08;OTP&#xff09;验证已经成为确保使用者身份验证的主要手段之一。然而&#xff0c;对于许多企业来说&#xff0c;发送OTP验证信息可能会…

fileinclude

看题目提示&#xff0c;应该是一道文件包含的题目&#xff0c;打开环境后直接告诉我flag在flag.php里 但是因为不知道绝对路径&#xff0c;不能直接利用file读取 查看源码后&#xff0c;发现里面嵌入了一段php代码 代码审计 首先&#xff0c;通过if( !ini_get(display_errors) …

springboot中banner.txt文件说明

springboot中banner.txt文件说明 通常在启动springboot项目的时候&#xff0c;&#xff0c;控制台会打印一些东西 比如&#xff1a; 如何自定义控制台输出的图形化符号 只需要在项目resources目录下创建一个banner.txt文件即可&#xff0c;因为启动的时候系统会自己检查该…

7.10作业

闹钟 mainWindow.ccp TCP服务器 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);server new QTcpServer(this);}MainWindow::~MainWi…

PDF文件转换成CAD图纸怎么做?简单好用的转换方法分享

CAD文件可以进行更加复杂的编辑&#xff0c;例如添加图层、修改线条颜色和粗细等&#xff0c;而PDF文件则只能进行简单的编辑操作。CAD软件中还可以添加文字注释、标注、尺寸和符号&#xff0c;这些功能大大提高了设计的灵活性和精度。下面给大家分享几种能够将PDF文件转换成CA…

交流充电桩通信方式和模块设计介绍

交流充电桩是新能源汽车充电系统的主要设备之一&#xff0c;可分为即插即用、刷卡取电和联网对接云端三种。即插即用&#xff0c;用户直接将充电枪连接到车辆上&#xff0c;就可以开始充电&#xff1b;刷卡取电&#xff0c;用户可以使用刷卡等方式取得充电权限&#xff0c;并根…

打印机一直重复打印不停止

打印一张纸&#xff0c;打印机一直重复打印不停止这个问题其实很简单&#xff0c;一般情况下是因为双向打印不兼容的问题&#xff1b; 选中打印机&#xff0c;点击右键&#xff0c;在弹出的菜单中选择“打印机属性” 在弹出的窗口中点“端口”&#xff0c;将“启用双向支持”前…

实现流程编排设计器的心路历程

接上回《「AntV」使用AntV X6实现流程编排设计器》一文说到&#xff0c;流程编排设计器的实现方案是将低代码引擎和AntV X6作为画布相结合。 为什么会有这样的想法&#xff1f; 可行性 起因是业务中有用到低代码引擎的场景&#xff0c;它的交互形式、页面结构正好符合流程编…

超级实用~低生物量的样本如何进行污染控制

上次小编主要介绍了低生物量比如口腔、阴道等样本的常见微生物和污染物&#xff0c;但是测序技术的高灵敏度也放大了样本中DNA污染的影响&#xff0c;那么对于低生物量的样本如何进行污染控制就至关重要了~ 2019年在《Contamination in Low Microbial Biomass Microbiome Studi…

vue + el-table点击表头改变其当前样式

废话不多说&#xff0c;先看效果&#xff1a; 网上找了一大圈没有符合的&#xff0c;只能自己看着搞&#xff1a; 直接贴代码&#xff1a; <el-tableref"table":data"tableData"borderstripesort-change"changeColumn"><el-table-colu…

vue语法详解

以下页面就是用vue开发的 模板语法 注意 模板语法不能在标签属性中用 文本插值 {{ msg }} 使用JavaScript表达式 {{ number 1 }} {{ ok ? YES : NO }} {{ message.split().reverse().join() }} 使用HTML 双大括号将会将数据插值为纯文本&#xff0c;而不是HTML&…

Apikit 自学日记:测试数据集

测试数据集 添加数据集的变量 在测试用例详情页面中&#xff0c;您可以点击上方的 测试数据 标签&#xff0c;进入用例的数据管理页面。在这里您可以添加多组测试数据&#xff0c;以及每组测试数据的变量。 在添加数据集前&#xff0c;我们需要设置数据集中存在什么变量。可以…

Qt:记录一下好看的配色

qss代码 窗体背景色 background-color: #ED6927; border-top-left-radius:35px;border-top-right-radius:35px;border-bottom-right-radius:0px; border-bottom-left-radius:0px;background-color: #203A32; border-radius:35px; border-top-left-radius:0px;border-top-righ…

如何用一部手机进行人体全身三维扫描

人体建模的应用真的是涵盖到了我们生活中的方方面面&#xff0c;真人潮玩、服饰定制、医疗康复、3D数字人等等领域&#xff0c;都离不开人体建模。 提到给人体建模&#xff0c;大家脑海里第一个浮现的画面&#xff0c;大多会是坐在电脑屏幕前&#xff0c;打开某个熟悉的建模的…

从本地目录和S3目录生成Classpath字符串的最佳实践

从一个目录生成Classpath字符串是一个非常常见的问题&#xff0c;在使用命令提交一个Java、Spark作业时会经常遇到。通常遇到的遇到情况是&#xff1a;将本地目录下的Jar文件拼接成一个Classpath字符串&#xff0c;这时&#xff0c;通常我们可以使用这样的命令&#xff1a; sp…