使用fs模块(导入)
const fs = require("fs");
目录结构如下
基本使用方法如下
fs.readFile('路径','可选参数',(err,data) => { 回调函数,错误有限原则 })
//index.jsconst fs = require("fs");fs.readFile("./1.text", "utf-8", (err, data) => {console.log(data);});
// 1.texthello world!
运行结果
基本使用方法如下
fs.writeFile('路径','写入内容','可选参数',(err,data) => { 回调函数,错误有限原则 })
// index.jsconst fs = require("fs");fs.writeFile("./2.text", "hello world鸭", [], () => {console.log(111);});
运行结果
写入成功
writeFile的结果是覆盖性的,也就是第二次的执行结果不会添加到第一次的后面而是直接替换整个文件
某些变量是可以在node中直接使用而无须导入的,__dirname,当前执行文件目录的绝对路径
console.log(__dirname)
执行结果
node的系统path模块提供了一些更高级的操作路径的方法
const path = require('path')
基本使用
path.join(...[paths])
const path = require("path");console.log(path.join(__dirname, "));
const path = require("path");const urlName = path.join(__dirname, ");console.log(path.basename(urlName));
运行结果
node.js用于创建web服务器的模块
服务器和普通电脑的区别在于,服务器安装了web服务器软件,IIS,Apache等,通过安装这些服务器软件,就可以将一台普通电脑变成一台web服务器。
导入http模块
1、引入http模块
const http = require('http')
2、创建web服务实例
const server = ateServer()
3、监听客户端的请求动作
("request", (req, res) => {// req是请求对象 res是返回对象console.log(req, res);});
4、监听端口启动服务器
server.listen("3001", () => {console.log("嘿嘿嘿 我的服务在localhost:3001端口上启动成功啦!");});
执行index.js文件
此时在浏览器打开localhost:3001会将请求信息打印到终端上
server服务器监听浏览器的请求动作的第一个参数req具有以下的key
url:从哪儿发来的请求
method:请求的方法
server服务器监听浏览器的请求动作的第二个参数res具有以下的key
setHeader:一个方法,用于设置响应头
end:一个方法,用于向浏览器端返回数据
以模块的来源进行分类,可以将Node.js中的模块分为以下三大类 系统模块如(fs,path,http),自定义模块用户自定义的,第三方模块用户引入的
引入方法都是使用require
const 模块名 = require('xx路径')
思考如下问题
为什么在每个node.js模块中,我们都可以自由的使用require、module这些没有定义过的变量用于模块导入导出呢?
《深入浅出node.js》如是说
实际上,每一个node模块都是被一个函数包裹起来的闭包(正是因此在node.js文件中模块才不会污染到全局变量)
(function(exports, require, module, __filename, __dirname) {// 模块内容});
从模块化原理一章中可以得知无需引入可以直接使用module对象。那么module对象里面到底有什么呢?百闻不如一见直接打印
console.log(module)
从这张图中我们也知道了为什么可以直接使用 port
在node模块中,我们可以使用ports将模块里的变量或函数暴露给其他模块进行使用。其他模块使用require引入之后就可以使用。(模块默认导出为空对象{},模块导出永远以ports的导出对象为准)如
ports = { name:'wxs'}
!!!!
需要注意的是,如果我们需要实现上例
以下三种写法都是正确的
ports = { name:'wxs'}ports.name = 'wxs'exports.name = 'wxs'
但是如果写成这样就会导出失败
exports = { name:'wxs' }
接下来开启下一章的内容
首先给出答案,没有区别,在node文件中打印
ports === exports
直接说明 exports和ports指向的是同一个对象,但是node只以ports的导出对象为准。如果写成exports = 新对象的形式就改变了exports的指向,改变之后的exports就不指向ports了,从而无法导出。
commonJS是node遵循的模块化规范。不要把这个想的有多复杂,我们在刚刚已经把它用的差不多了,在这一小节中总结一下。
CommonJS规定
在node.js中,在js文件中使用的第三方模块又称作包。不同于内置模块与用户自定义模块,包是网络上的第三方个人或者第三方团队开发
在项目中使用第三方包的命令
npm i 包名称
安装之后项目目录文件夹会多出两个文件
node_modules和package
其中node_modules文件夹包含了所下载的全部第三方包,package-lock记录了包名称、版本号等信息。
执行
npm uninstall xxx包名称
之后会自动将包依赖从package-lock中移除
express之于node,有点类似于jquery之于js原生代码。比如我们要新建一个web服务器,原生node写法如下
安装
npm i express
const express = require("express");const app = express();("/", (req, res) => {res.send({name: "wxs",});});app.listen(3000, () => {console.log("your localServer is running on localhost:3000");});
且相比较之下,express还有很多优势,如中间件,创建静态资源服务器等…
express提供了一个很好用的方法用于创建一个静态资源服务器。express.static(),例如,通过
express.static('public')
就可以将public目录下的css、图片、icon等静态资源暴露出去。
express在指定的目录中查找静态资源,因此,目录名不会出现在URL中,举个小🌰
编辑index.js,在 const app = express() 后新加一行
app.use(express.static("public"));
第二步,在文件同级目录下新建public文件夹中新建images文件夹,再随便找张图片放进去
第三步
如果有多个静态资源文件夹,只需多次调用即可,另外,如果想在取静态资源时加上路径前缀,可以写成 app.use('/xxx(路径)',express.static('xxx(路径)'))
的形式
在express中,路由指的是客户端的请求和服务端请求函数之间的关系,基本调用关系如下
app.METHOD('URL',处理函数)('url',(req,res) => {处理函数})
为了方便对express进行更好的管理,express不建议将路由直接挂载到app上,而是推荐将路由抽离成单独的组件。
实际上使用路由模块就两步,第一步编写路由模块导出,第二步引入并使用
const express = require("express");const route = express.Router();("/", (req, res) => {d("您现在看到的是首页");});ports = route;
const routeTest = require("./routes/routerTest");const express = require("express");const app = express();app.use(routeTest);app.listen(3000, () => {console.log("your localServer is running on localhost:3000");});
直接运行,postman结果如下
路由模块添加统一前缀的方法和添加静态资源服务器时一致,直接改写app.use加上第一个参数
app.use('/XXX',routeTest)
express中间件本质上就是一个function处理函数,与路由处理函数不同的是,中间件处理函数必须包含next参数,而路由处理函数只需要包含req和res,客户端发送请求后,服务端会根据中间件定义的顺序依次调用中间件。
express中的中间件是共享一套req和res的,因此我们可以在上游中间件中为res,req提供属性和方法供下游中间件使用,tips:中间件一定要调用next方法,否则无法过渡到下游中间件
next参数是一个函数,它是中间件跳转的关键,表示将操作转交给下一个操作或者路由。百闻不如实际操作
直接定义一个中间件
const middleWare = (req,res,next) => {console.log('我是一个中间件')// 必须调用!!!不然无法跳转至下一个中间件会造成流程阻断next()
}
上一节中我们已经定义了一个最简单的中间件函数,这一章将要使用它并使它全局生效。编辑index.js文件如下
const express = require("express");const app = express();const middleWare = (req, res, next) => {console.log("我是一个中间件");// 必须调用!!!不然无法跳转至下一个中间件会造成流程阻断next();};app.use(middleWare);("/", (req, res) => {res.send("hello world");});app.listen(3000, () => {console.log("your localServer is running on localhost:3000");});
代码表明这在处理get请求之前先经过middleware中间件,控制台会打印文字,看实际效果
全局中间件是在服务端处理任何请求时都会执行的中间件,而局部中间件只有在服务端处理某特定请求时才会执行。
基本使用
('xxx(请求地址)',middleWare,(req,res) => {})
定义中间件必须要在定义路由之前
由于中间件执行顺序是从上至下的,所以定义中间件需要在定义路由之前,否则中间件无法正常使用。
客户端发过来的请求可以连续调用多个中间件
执行完中间件的逻辑代码一定要调用next函数
多个中间件之间是共享req和res对象的,因此下游中间件可以接收到上游中间件处理之后的req和res
const express = require("express");const route = express.Router();("/", (req, res) => {d("您现在看到的是首页");});ports = route;
("/", (req, res) => {throw new Error("服务器发生了错误");res.send("hello world");});app.use((err, req, res, next) => {res.send("很抱歉服务器发生了错误");});
错误级别中间件必须注册在所有路由之后!
app.use(express.static('xxx(路径名)'))
express.json
用于解析JSON格式的请求体的数据
// 配置处理json格式请求体的中间件app.use(express.json())
express.urlencoded
用于解析URL-encoded格式的请求体数据
// 配置处理URL-encoded格式请求体的中间件app.use(express.urlencoded())
// 下载npm i xxxconst XXX = require('xxx');app.user(XXX)
自定义中间件很重要,值得新开一小节,上文中已经说到,中间件本质上是一个函数。所以自定义中间件似乎也没有辣么难啦。自定义行为因人而异,这里只简要介绍基本使用
const myMiddleWare = (req,res,next) => {console.log('这里是我自定义的逻辑');next()}app.use(myMiddleWare )
我们如果需要在中间件中处理客户端发送过来的数据,需要使用req对象监听data事件。
('data',() => { // 回调函数 })
如果客户端的数据接收完毕会触发end事件
('end',() => { // 回调函数 })
最终我们开发完中间件之后往往会将它封装成函数。
本文发布于:2024-01-28 22:13:01,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170645118410650.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |