node基础 ,nodejs的express框架(三)

启程express

  • 安装npm i express -S

  • 1:引入express第三方对象

  • 2:构建一个服务器对象

  • 3:开启服务器监听端口

  • 4:处理响应

  • 在express中,保留了原生http的相关属性和函数

app.use(路由路径,fn)

  • 小练习

    • 选择性荤菜素菜

  • 用户/abc/def的请求

    • 选择性调用app.use('/abc',fn)的中间件

    • 但是内部req.url则去除了/abc这个暗号

  • app.use(fn)是任何请求都会触发执行的

中间件类别(请求与响应之间的事情)

  • 应用级中间件 app.use(事fn)

  • 路由级中间件

    • 1:获取路径级中间件

    • 2:配置路由

    • 3:加入到应用程序控制中app.use(router);

  • 内置中间件

    • 处理一些静态资源文件的返回(设置将某个目录下的资源文件向外暴露)

      • 当url匹配上我设置的目录下的子文件后,自动返回该文件

      • 加入到应用程序控制中app.use(内置中间件);

  • 第三方中间件

    • 更方便的处理cookie/session,简易的解析post请求体数据

    • 在npm上下载并使用

    • 加入到应用程序控制中app.use(第三方中间件);

  • 错误处理中间件

    • 在express中统一处理错误next(err)

路由中间件

  • 一个请求进来(总网线),分发到各自不同的处理(分多根网线给其他人)

    • 分流

  • 后端路由

    • (请求方式 + URL = 判断依据)(分流的判断依据) -> 做不同的处理(分流后的行为)

  • 使用步骤

    • 1:获取路由中间件对象 let router = express.Router();

    • 2:配置路由规则 router.请求方式(URL,fn事)

      • fn中参数有req,res,next

    • 3:将router加入到应用app.use(router)

 

路由

 

 

res扩展函数

res.download('./xxx.txt') // 下载文件
res.json({})  // 响应json对象
res.jsonp(数据) // 配合jsonp   要求客户端请求的时候也是jsonp的方式, 并且callback=xxx
res.redirect()  // 重定向 301是永久重定向, 302临时重定向
res.send()    // 发送字符串数据自动加content-type
res.sendFile() // 显示一个文件
res.sendStatus() // 响应状态码
  • 总结

    • res.json() 响应数据,最常用 , 返回ajax数据

    • redirect() 重定向

    • download() 下载

    •  

       

    • jsonp() 跨域处理

 

模板渲染


使用art-template模板引擎

  • 下载express-art-template art-template

  • app.js中配置

    • 注册一个模板引擎

      • app.engine('.html',express-art-template);

        • 设置默认渲染引擎app.set('view engine','.html');

    • res.render(文件名,数据对象);

    • express这套使用,默认在当前app.js同级的views目录查找

 

服务端处理错误和404页面找不到

  • 404页面响应router.all('*',()=>{} )

  • 触发错误

    • next(err);

    • 处理错误 app.use( 4参数函数 )

nodemon

  • 修改代码自动重启

  • 安装全局命令行工具 npm i -g nodemon

  • 进入到指定目录命令行 nodemon ./xxx.js

 

 

server1.js

// - 1:引入express第三方对象
const express = require('express');
// - 2:构建一个服务器对象
// 原生的
// let server = http.createServer();
let app = express();

// - 3:开启服务器监听端口
app.listen(8888,()=>{
  console.log('服务器启动在8888端口');
});

// - 4:处理响应
// 1: app.use是请求与响应中执行的一件事,按代码顺序来执行
// 2:next() 是放行到下一件事的开关
// 3:如果全next,最终没有end页面数据,框架帮我们处理了
//     status:404

// 用户选择性url开头的部分,选择性调用对应的事
app.use('/sucai',(req,res,next)=>{
  console.log('萝卜');
  next(); // 放行开关
});
// 一件事
app.use('/sucai',(req,res,next)=>{
  console.log('白菜');
  next();
});
app.use('/huncai',(req,res,next)=>{
  console.log('牛肉');
  next();
});
app.use('/huncai',(req,res,next)=>{
  console.log('羊肉');
  next();
});

 

server2.js

const express = require('express');

let server = express();

// - 1:获取路由中间件对象 let router = express.Router();
let router = express.Router();
// - 2:配置路由规则 router.请求方式(URL,fn事)
router.get('/login',(req,res) => {
  res.end('login page');
})
.get('/register',(req,res) => {
  res.end('register page');
})
//   - fn中参数有req,res,next
// - 3:将router加入到应用server.use(router)
server.use(router);

server.listen(8888);

server3.js

const express = require('express');

let server = express();

// - res.json() 响应json数据,最常用 , 返回ajax数据
// - redirect() 重定向
// - download() 下载
// - jsonp() 跨域处理


// - 1:获取路由中间件对象 let router = express.Router();
let router = express.Router();
// - 2:配置路由规则 router.请求方式(URL,fn事),链式调用
router.get('/json',(req,res) => {
  res.json([{name:'jack'}]);  // res.end只能响应string||读文件中的data Buffer
})
.get('/redirect',(req,res) => {
  // 重定向到百度
  res.redirect('http://www.baidu.com');
})
.get('/jsonp',(req,res) => {
  res.jsonp('jack love rose');
})
.get('/download',(req,res) => {
  res.download('./app.js');  // app.js,注意文件是如何被下载成功的
  // 基于服务器回写的content-type。等头信息
})
// - 3:将router加入到应用server.use(router)
server.use(router);

server.listen(8888);

 

server4.js, 模板渲染,将html文件返回给浏览器,重要

const express = require('express');

let server = express();

// / - 注册一个模板引擎
//   - app.engine('.html',express-art-template);
      // 渲染文件的后缀名(引擎名称)
server.engine('.html',require('express-art-template'));

// 区分开发和生产环节的不同配置,了解即可
// server.set('view options', {
//     debug: process.env.NODE_ENV !== 'production',
//       // debug :  不压缩,不混淆,实时保持最新的数据
//       // 非debug: 压缩/合并, list.html 静态数据不回实时更新(服务器重启才更新)
//     imports:{   
//       // 数据的导入,和过滤显示的操作
//       num:1,
//       reverse:function(str) {  
//         return '^_^' + str + '^_^';
//       }
//     }
// });

// 配置默认渲染引擎,就是ssr渲染,将html返回给浏览器,默认去找与server4.js同级的view文件夹的.html文件
server.set('view engine','.html');

let router = express.Router();

router.get('/hero-list',(req,res) => {
  res.render('list.html',{
    heros:[{name:'貂蝉'},{name:'吕布'},{name:'董卓'}]
  });
})

server.use(router);

server.listen(8888);

 

server5.js, 服务端处理错误和404找不到页面

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

let server = express();

server.engine('.html',require('express-art-template'));

// server.set('view options', {
//     debug: process.env.NODE_ENV !== 'production',
// });

// 配置默认渲染引擎
server.set('view engine','.html');

let router = express.Router();

router.get('/',(req,res,next) => {
  console.log('请求进来了?',req.url);
  // 目录下没有该文件,会读取不到文件
  let errorPath = './abc/e.txt';
  try {
    // 同步读取服务器中的文件
     fs.readFileSync(errorPath);
    //  将view文件夹下index.html返回
     res.render('index');
  } catch (err) {
    // throw err;  // 给用户看到了异常,太恶心
    next(err); // 触发一个具备4个参数的中间件函数
  }

})
// 最后一条路由中,不论什么请求方式,什么路径,比如地址栏输出服务端没处理的/user路由
.all('*',(req,res)=> {
  res.send('地址错误,您去首页吧');
})

// 要把public下的文件暴露出来
// server.use('/public',express.static('./public'));  
// 当虚拟目录/public被匹配以后,未来url都会去除掉/public

server.use(router);


// 没找到正确的html返回,比如用户地址栏输入/根路径,但是读取文件有错误 处理错误(参数位置错误优先) -> 优雅的用户体验
server.use((err,req,res,next) => {
  res.send('<h1>亲爱的用户,您访问的页面,有事儿了,<a href="/">去首页看看?</a></h1>');
})


server.listen(8888);

注;1.服务器只处理了/根路由, 如果用户地址栏输入/user, 服务器没有处理这个路由,那么会报错,所以需处理router.all(),来提示错误,404

2.如果用户地址栏是/更路径,但是服务器读取文件时有错误,需要server.use(),来处理错误。

这两种优化处理错误方式都很常见

 

posted @ 2021-03-09 14:46  全情海洋  阅读(236)  评论(0编辑  收藏  举报