当前位置: 首页 > news >正文

Node.js学习

概述

Node.js 是一个基于 Chrome V8 引擎 JavaScript 运行时环境,允许在服务器端运行 JavaScript 代码。它采用事件驱动非阻塞 I/O 模型,适合构建高性能、可扩展的网络应用,尤其擅长处理实时应用和大规模数据密集型场景

背景

  1. JavaScript 的普及
    JavaScript 最初是浏览器端的脚本语言,但随着 Web 2.0 和 AJAX 技术的兴起,JavaScript 在前端开发中变得至关重要。开发者希望能在服务器端也使用 JavaScript,以实现前后端语言统一,简化开发流程。

  2. 高性能服务器需求
    传统服务器(如 Apache)采用多线程模型处理请求,每个请求占用一个线程,资源消耗大且难以应对高并发。Node.js 通过事件驱动和非阻塞 I/O模型,解决了这一问题,能够高效处理大量并发请求。

  3. Chrome V8 引擎的出现
    2008 年,Google 发布了 Chrome 浏览器,其 JavaScript 引擎 V8 性能卓越,能够快速编译和执行 JavaScript 代码。Node.js 的创始人 Ryan Dahl 受到启发,利用 V8 引擎构建了一个服务器端运行时环境,使 JavaScript 能够脱离浏览器运行。JavaScript 代码直接编译为机器码,而不是解释执行,从而大幅提升执行速度。

  4. 事件驱动编程的兴起
    事件驱动编程模型在 GUI 和网络编程中广泛应用,Ryan Dahl 认为这种模型非常适合处理高并发的网络请求。Node.js 采用事件循环机制,能够高效处理 I/O 操作,避免线程阻塞。

  5. Ryan Dahl 的初衷
    Ryan Dahl 在开发 Node.js 时,目标是创建一个轻量级、高效的平台,专注于实时应用和高并发场景。他希望通过非阻塞 I/O 和事件驱动模型,解决传统服务器的性能瓶颈。

  6. 开源社区的推动
    Node.js 于 2009 年开源后,迅速吸引了大量开发者。其轻量级、高性能的特点,加上 JavaScript 的广泛使用,使其在短时间内获得了广泛关注和支持

安装

node.js官网

无BOM和DOM

node,js中顶级对象是globle对象

fs(file system)模块

与硬盘交互
导入fs模块

let fs=require("fs")

写入|追加|文件流式

writeFile|appendFile|createWriteStream
打开文件是需要消耗资源的,文件流式可以减少打开关闭文件的次数,适用于大文件高频次的写入

异步

let fs=require("fs")
fs.writeFile("./testFile.txt","测试file",err=>{if(err){console.log("写入失败")}else{console.log("写入成功")}
})fs.appendFile("./writeFile.txt","asdasd",err=>{if(err){}else{console.log("追加成功")}
})let ws=fs.createWriteStream("./writeFile.txt")
ws.write("阿萨德哈手机侃大山客户卡几哈")
ws.close()

同步

同步无callback函数
writeFileSync|appendFileSync

读取

readFile|readFileSync|createReadStream

let rf=fs.readFile("./writeFile.txt",(err,data)=>{if(err){}else{console.log(data.toString())}
})
// chunk 循环去读,一次只能读一块:65536字节=64KB
rs=fs.createReadStream("writeFile.txt")
rs.on('data',chunk=>{console.log(chunk.toString())
})
// 读取结束
rs.on("end",()=>{console.log("读取完成")
})

读取-写入

let data=fs.readFileSync("./writeFile.txt")
fs.writeFileSync("./writeFileCopy.txt",data)let rs=fs.createReadStream("./writeFile.txt")
let ws=fs.createWriteStream("./writeFileCopyStream.txt")rs.on("data",chunk=>{ws.write(chunk)})rs.on("end",()=>{console.log("读取完成")})

重命名==移动

rename|renameSync

fs.rename("./writeFileCopyStream.txt","./1.txt",rr=>{
})fs.rename("1.txt","./a/11.txt",err=>{console.log(err)
})

删除

unlink|unlinkSync

fs.unlink("./a/11.txt",err=>{if(err){}else{console.log("删除成功")}
})

node.js 14 新增
rm|rmSync

fs.rm("./writeFileCopy.txt",err=>{if(err){}else{console.log("删除成功")}
})

文件夹

创建文件夹

fs.mkdir("a"err=>{
console.log(err)
})

递归创建

fs.mkdir("a/b/c",{recursive:true},err=>{console.log(err)
})

删除文件夹

 fs.rmdir("aa",err=>{})

读取文件夹

fs.readdir("img",(err,data)=>{if(!err){console.log(data)}
})

补充: data.isDirectory() :是否文件夹 data.isFile():是否文件

路径问题

fs.writeFile("./aa.txt","adasdsad",err=>{console.log(err)
})

其创建文件以命令行为维度而不是当前文件所在位置为维度

绝对路径

__dirname:获取项目的绝对路径

path 模块

require(“path”)

resolve 路径拼接


console.log(path.resolve(__dirname,"test.html"))

sep 当前操作系统分隔符

console.log(path.sep)

路径解析

console.log(path.parse("C:\\Users\\xsx\\Desktop\\test\\hello.js")){root: 'C:\\',dir: 'C:\\Users\\xsx\\Desktop\\test',base: 'hello.js',ext: '.js',name: 'hello'
}

获取文件名|文件目录 扩展名

let str="C:\\Users\\xsx\\Desktop\\test\\hello.js"
console.log(path.basename(str))
console.log(path.dirname(str))
console.log(path.extname(str))// 
hello.js
C:\Users\xsx\Desktop\test
.js

http 模块

http资料

let http=require("http")let server=http.createServer((request,response)=>{response.end("hellt http server")
})
// 设置端口--回调
server.listen(9000,()=>{console.log("server start")
})

request

  • request.url
  • request.method
  • request.headers:返回对象

获取参数-post

        // 声明一个变量let body=""// 绑定data 事件request.on("data",chunk=>{body+=chunk})//  绑定 end 事件request.on("end",()=>{console.log(body)console.log("request end")})

url 模块

let url=require("url")

获取参数

get

let url=require("url")let server=http.createServer((request,response)=>{console.log(request.method)let urlParse=url.parse(request.url)console.log(urlParse)
// 
Url {protocol: null,slashes: null,auth: null,host: null,port: null,hostname: null,hash: null,search: '?name=sux&age=11',query: 'name=sux&age=11',pathname: '/search',path: '/search?name=sux&age=11',href: '/search?name=sux&age=11'
}})
// 设置端口--回调
server.listen(9000,()=>{console.log("server start")
})

response

  • 设置状态码:response.statusCode
  • 设置响应头: response.setHeader(key,value)
response.setHeader("content-type","application/json")`在这里插入代码片`
  • 设置响应体: response.write(),response.end()
    write可以有多个,但最后以唯一一个end()结束,或者直接end(value)

资源类型(MIME)

媒体类型(mime类型)是一种标准,用来表示文档、文件或字节流的性质和格式
HTTP服务可以设置响应头Content-Type来表面响应体的MIME类型,浏览器会根据类型去如何处理资源

  • html :text/html
  • css: text/css
  • js:text/javascript
  • png:image/png
  • jpg:image/jpeg
  • gif:image/gif
  • mp4:video/mp4
  • mp3:audio/mpeg
  • json:application/json
    对于未知资源类型:applicaton/octet-stream类型,浏览器遇到该类型时会对响应体内容进行独立存储,也就是我们常见的下载

模块(CommonJS)

导出:exports

核心:exports=module.exports={} 是一个对象

exports.name=value

module.exports 是 CommonJS 模块系统的默认导出对象。


module.exports="asdasdasdasd"module.exports={testModule,testModule2}

导入:require

const module1=require("./module1.js")
  • 导入时的路径写相对路径,且不能省略 ./或…/
  • 导入可以省略js或json后缀名
  • 如果导入的是文件夹,则首先会检测文件夹下package.json的main属性对应的文件。如果存在,则导入。如果不存在package或者main则或导入其文件夹下index.js或index.json。否则报错。
    注:js或json同时存在同名,则只会导入js
  • 导入node.js内置模块是,可直接require模块名字

包管理工具

  • npm
  • yarn
  • cnpm

npm (node package manager)

npm 是node.js官方内置的包管理工具,在node.js会默认安装npm

查看版本

在这里插入图片描述

初始化包

在这里插入图片描述
注: npm init -y 或 npm init --yes 会默认快速创建

搜索包

  • 命令行
    在这里插入图片描述
npm s/search 关键字
  • 去网站搜索 https:// www.npmjs.com

安装

npm i/install :根据package.json和package-locjk.json的依赖声明安装整个项目依赖

npm i/install <报名>// npm install uniq
npm 安装指定版本的包
npm i <包名@版本号>
npm 删除包
npm r/remove <包名>
// 全局删除
nppm r/remove -g  <包名>

运行之后文件夹下会产生两个资源

  • node_modules 用来存放下载的包
  • package-lock 包的锁定文件,用来锁定包版本

引入

const uniq=require("uniq")const arrp=[1,2,3,4,5,5,5,5]
uniq(arrp)

require导入npm包的基本流程
在当前文件下node_modules下去寻找,未找到会到上级目录的node_modules去寻找,直至到磁盘根目录。

生成、开发、全局版本

  • npm i -S 默认
  • npm i -D
  • npm i -g
    在这里插入图片描述
    nodemon: 自动重启node程序
    npm root -g: 全局包的安装位置

配置命令别名

通过配置命令别名可以更简单的执行命令
配置package.json的script属性

"scripts": {"test": "echo \"Error: no test specified\" && exit 1","dev":"node test.js"},
npm run dev

npm 配置淘宝镜像

npm config set registry https://registry npmmirror.com/

cnpm(了解)

cnpm是淘宝构建构建的npmjs,con的完整镜像,也称淘宝镜像,网址https://npmmirror.com/
cnpm服务部署在国内阿里云服务器上,可以调高包的下载速度。
淘宝镜像为只读与官方同步频率为10分钟一次

安装

通过npm命令去安装cnpm

npm install -g cnpm --register=https://npmmirror.com/

cnpm与npm使用命令相同

NVM (node version manager)

解决:多个node.js版本的下载、切换

  • nvm list available 显示所有可以下载的node.js版本
  • nvm list 显示已安装的node.js版本
  • nvm install <版本号> 安装
  • nvm user <版本号> 使用

Express

express是一个基于node.js平台极简、灵活的WEB应用开发框架。官网地址:https://erpressjs.com.cn/

安装

npm intall express

创建

const express=require("express")// 创建请求应用
let  app=express()
// 创建路由请求
app.get("/home",(req,res)=>{res.setHeader("content-type","text/html;charset=utf-8")res.write("阿萨德哈健康会尽快")res.end()
})
// 监听端口,启动服务
app.listen(9000,()=>{console.log("启动正常")
})

路由

官网定义:路由确定了应用程序如何响应客户端对特定端点的请求
路由的组成
一个路由的组成有请求方法路径回调函数
格式:

app.<method>(路径,回调函数)
method:
  • get
  • post
  • all

request

  • request.method
  • request.url
  • request.pathname
  • request.ip
  • request.headers
  • request.get(name) :获取请求头中指定的name
  • requset.query:参数
路由参数

占位符 :id

// 请求路径:http://127.0.0.1:9000/9999.htmlapp.get("/:id.html",(req,res)=>{console.log(req.params.id)  //  9999})

reseponse

在这里插入图片描述

express 中间件(类似java–filter)

介绍

中间件本质上是一个函数

作用

中间件的作用就是使用函数封装的公共操作,简化代码。

类型

  • 全局中间件
  • 路由中间件
全局中间件

全局配置

const express= require("express")
const fs=require("fs")
const path=require("path")
// 创建
function recordMiddleware(req,res,next){let {url,ip}=reqconsole.log(__dirname)fs.appendFileSync(path.resolve(__dirname,"./ip.txt"),`${url}--${ip}\r\n`)// 继续往下执行next()
}const app=express()
// 加载配置使用
app.use(recordMiddleware)
app.get("/get",(req,res)=>{res.send("success")
})app.listen(9000,()=>{console.log("启动成功")
})
路由中间件

路由配置


let routeMiddleware=(req,res,next)=>{if(req.query.code=="xusx"){next()}else{res.send("fail")}
}const app=express()
// app.use(recordMiddleware)
app.get("/get",routeMiddleware,(req,res)=>{res.send("success")
})app.listen(9000,()=>{console.log("启动成功")
})

express内置静态资源中间件

根据request.path去静态目录下查找然后直接输出

const app=express()
app.use(express.static(__dirname+"/public"))

文件目录
在这里插入图片描述

注:当请求路径为"/"时,会自动去目录下搜寻默认的index.html
在这里插入图片描述
在这里插入图片描述

获取post请求体-post入参

body-parser

const bodyParser=require("body-parser")//  请求体为json
const jsonParse=bodyParser.json()
// 请求体为form
const urlencodedParse=bodyParser.urlencoded({extended:false})
// 添加局部中间件
app.post("/postInfo",urlencodedParse,(req,res)=>{console.log(req.body)console.log(req.body.age)
})

路由模块化

express.Router()
app.use()

getRoute.js

const express=require("express")const getRouter=express.Router()getRouter.get("/getIndex",(req,res)=>{res.send("asdasd")
})module.exports= getRouter
const getRouter=require("./router/getRouter")
const app=express()app.use(getRouter)
// 可添加路由前缀
// app.use("/testGet",getRouter)   
app.listen(9000,()=>{console.log("启动成功")
})

模板引擎-ejs

变量

格式:<%= %>const ejs=require("ejs")const str1="学习"
let result=ejs.render(`早上开始<%= str1%>`,{str1:str1})

代码

格式:<%  %>
const ejs=require("ejs")
const isLogin=false
let result=ejs.render(`<% if(isLogin){ %><p>成功</p><% }else{%><p>失败</p><% }%>`,{isLogin:isLogin})

express 中使用ejs


const express=require("express")
const isLogin=true// 创建路由
const app=express()
// 设置所使用的模板引擎
app.set("view engine","ejs")
// 设置模板所在的目录
app.set("views",__dirname)app.get("/home",(req,res)=>{// 输出res.render('home',{isLogin})
})
app.listen(9000,()=>{console.log("启动成功")
})

home.ejs 后缀名ejs

<!DOCTYPE html>
<html><body><% if(isLogin){ %><p>成功</p><% }else{%><p>失败</p><% }%></body>
</html>

express-generator

是一个用于快速生成 Express.js 应用骨架的命令行工具。通过它,你可以轻松创建一个包含基本目录结构和文件的 Express 项目,从而节省手动配置的时间。

主要功能

  • 生成项目结构:自动创建标准的 Express 应用目录,如 routes、views、public 等。

  • 设置基本路由:生成默认的路由文件,帮助你快速开始开发。

  • 配置模板引擎:支持多种模板引擎(如 EJS、Pug、Handlebars),并自动配置。

  • 提供静态文件支持:自动设置 public 目录用于存放静态资源。

安装

npm install -g express-generator

使用

express [文件名]

文件结构

在这里插入图片描述

相关文章:

  • Vite/Rollup 模块热更新
  • Python内置函数---bytes()
  • MySQL基础增删改
  • CDN加速http请求
  • 百万点数组下memset、memcpy与for循环效率对比及原理分析
  • 【大模型与AIGC深度解析】从核心概念到行业应用
  • Python实现孔填充与坐标转换
  • 网络编程——通信三要素
  • GitLab_密钥生成(SSH-key)
  • 第4天:Linux开发环境搭建
  • 【JavaScript】详讲运算符--算术运算符
  • 时间自动填写——电子表格公式的遗憾(DeepSeek)
  • 品融电商:领航食品类目全域代运营,打造品牌增长新引擎
  • EasySearch 服务昨天还好好的,为什么今天突然访问不了了?
  • Java面试题汇总
  • FI固定资产折旧码的功能用途及其配置介绍
  • 【CSS】层叠,优先级与继承(三):超详细继承知识点
  • 推荐系统排序阶段核心要点:多目标排序模型详解
  • UnoCSS原子CSS引擎-前端福音
  • 15.FineReport动态展示需要的列
  • 吃菜和吃肉,哪个更“增肌”?
  • 百年前的亚裔艺术家与巴黎
  • 上海市长会见璞跃全球创始人亚美迪,建设国际AI创新创业网络中心节点
  • 呈现“民族脊梁型爱国学府”曲折辉煌的办学历程,这个展览开幕
  • “低头捡星光”,艺术创作直面三江源生态保护
  • 普京签署有关批准俄罗斯与伊朗全面战略伙伴关系条约的联邦法令