node.js五天集训基础

express与mongodb结合

第一天

什么是跨域
就是协议,域名,端口必须相同,只要有一个不同就是跨域
node的安装
下载地址:https://nodejs.org/zh-cn/

查看安装是否成功

安装好后,在终端中查看node版本

node -v

安装node时,会自动安装npm,可在终端中查看npm版本

npm -v

安装插件:Code Runner(就可以用Run Code调用了)
想要出现对node代码的提示,安装第三方库node (输入代码npm i @types/node)
在这里插入图片描述
如何运行,右键,在终端中打开;

认识node的全局对象global

像浏览器的全局对象:window
Node的全局对象:global

  • global.console
    输出
  • global.setTimeout
//延迟2秒后打开
setTimeout(function() {
    
    
    console.log("123");
}, 2000);
  • global.setInterval
//每隔两秒执行一次代码,停止按Ctrl+c;
setInterval(function() {
    
    
    console.log("123");
}, 2000);

认识CommonJS:
CommonJS规范内容:

  • 一个js文件就是一个模块
  • 模块内所有的变量均为局部变量,不会污染全局
  • 模块中需要提供给其他模块使用的内容需要导出
  • 导出使用exports.xxx = xxx或module.exports=xxx或this.xxx=xxx
  • 其他模块可以使用require函数导入

不同模块之间相互调用:
需要先导出数据,才可以在另外一个模块中调用
导出后被调用的模块会自身执行一次

//a模块
//三种导出方法
var a = 3;
//第一种
exports.a = 3; //导出{ a:3 }
exports.b = 123; //导出{ a:3 b:123 }
//第二种
module.exports = 3; //导出3
module.exports = {
    
     //导出{a:"hello"}
	a: "hello"
}
    //第三种
this.a = 3; //导出{ a:3 }
this.b = 123; //导出{ a:3 b:123 }


//b模块
//需要用require去调用,"./"是返回上级目录
var result = require("./a");
console.log(result);

注意事项:

exports.a = 1;
exports.b = 2;
module.exports.c = 3;
//调用得到的结果为{ a: 1, b: 2, c: 3 },因为exports没有被重新赋值


exports.a = 1;
exports.b = 2;
module.exports = {
    
    
    c: 3,
}
//调用得到的结果为{ c: 3 },因为exports被重新赋值



module.exports = {
    
    
    c: 3,
}
exports.a = 1;
exports.b = 2;
//调用得到的结果为{ c: 3 },具体原因看下图(只要module.exports重新赋值,就跟exports毫无关系)

在这里插入图片描述
理解

//模块一
module.exports = function(){
    
    };
exports.a = 1;
exports.b = 2;

//模块二
var result = require("./a");
console.log(result.a);
//输出结果为undefined。只要module.exports被重新赋值,exports将不会有用处
//如果模块a啥都没有,模块b调用模块a的东西
var result = require("./a");
console.log(result);
则结果为{
    
    },不会报错

重点,去理解伪代码

// 下面是伪代码
function require(modulePath){
    
    
  // modulePath 为模块路径
  var moduleId = getModuleId(modulePath); // 获取模块的绝对路径
  if(cache[moduleId]){
    
    
    // 是否有缓存
    return cache[moduleId];
  }
  // 没有缓存
  
  // 该函数用于执行一个模块
  function execModule(module, exports, __dirname, __filename){
    
    
    // module 用于导出的对象
    // exports 用户导出的对象
    // 导入的模块所在目录的绝对路径
    // 导入的模块的绝对路径
    
    这里是导入的模块的代码
  }
  
  var module = {
    
     
    exports: {
    
    } 
  };
  execModule.call(module.exports, module, module.exports, 模块目录绝对路径, 模块绝对路径);
  cache[moduleId] = module.exports; // 缓存结果
  return module.exports;
}

模块的查找

  • 模块路径以./或…/开头:从当前模块路径出发查找
  • 模块路径不是以./或…/开头
    看是否是内置模块
    看是否在node_modules目录中

省略
如果模块路径中省略了后缀名,则认为后缀名是.js
如果模块路径中省略了文件名,则认为文件名是index.js

npm的使用

npm config set registry http://registry.npm.taobao.org/ # 配置npm安装源,加速下载
npm init # 使用npm初始化,生成package.json
npm i 第三方库的名称 # 安装第三方库
npm i # 按照package.json的记录安装第三方库
npm i -D 第三方库的名称 # 使用开发依赖的方式安装第三方库
npm i --production # 按照package.json的记录安装第三方库,但不安装devDependencies

先打开终端运行,输入npm config set registry http://registry.npm.taobao.org/
然后输入npm init
之后一直回车就可以了

然后安装包
输入npm i lodash 可以下载一个包
然后就可以使用了
如何使用第三方库

var _ = require("lodash");
var newArr = _.chunk([1, 2, 3, 4, 5, 6], 2);
console.log(newArr);
//输出结果[ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ]

内置模块 path
path.resolve(…pathsegments)
该函数可以将多个路径片段合并为一个完整的绝对路径
注意,片段中的./和…/相对的是工作目录

//第一种写法
var path = require("path");
var result = path.resolve("./nodejs", "a.js"); //把多个路径拼接成一个绝对路径
console.log(result);

//第二种写法(主要这样写)
var path = require("path");
var result = path.resolve(__dirname, "nodejs/a.js"); //把多个路径拼接成一个绝对路径
console.log(result);
//输出d:\谷歌下载地\wed\nodejs\nodejs\a.js

内置模块fs

fs.readFile(path, callback)

读取指定文件的内容

var fs = require("fs");
var path = require("path"); //得到绝对路径 
var filename = path.resolve(__dirname, "text.txt");
//要写utf-8,不写的话输出是二进制编码
fs.readFile(filename, "utf-8", function(err, content) {
    
     //第一个参数是错误,第二个参数是文件内容
    console.log(content);
});
//输出为《你好啊》

在这里插入图片描述

第二天

数据库
数据库(DB)是一种数据持久化的技术

它分为三大类,分别是:

  • 关系型数据库:mysql、sqlserver、oracle等
  • 非关系型数据库:mongodb、redis等
  • 面向对象数据库:db4o

非关系型数据库的特点:

  • 大量数据的存取速度快
  • 使用简单,学习成本低
  • 难以表达复杂的数据关系

非关系型数据库又分为很多子类别,mongodb是非关系型数据库中的文档型数据库
mongodb的安装
mongodb
robo 3T

核心概念
db:数据库
collection:集合,类似于js中的数组
document:每个集合中的文档,类似于js中的对象

  • Primary Key:主键,每个文档的唯一编号
  • field:文档中的字段,类似于对象中的属性

在这里插入图片描述
在node中使用mongodb
安装mongoose

npm i mongoose

  • 创建连接
var mongoose = require("mongoose");
mongoose.set("useCreateIndex", true); // 新版本对索引的处理方式有所变化,无此代码会有警告
mongoose.connect("mongodb://localhost/test", {
    
    //连接,(主机名localhost),(数据库名称test),最主要的
  useNewUrlParser: true, // 新版本对连接字符串的解析有更好的支持,无此代码会有警告
  useUnifiedTopology: true, // 新版本对数据库的监事引擎有更好的支持,无此代码会有警告
});

mongoose.connection.on("open", function(){
    
    
  console.log("连接已打开");
});

任何数据库操作,都必须建立在连接通道之上,因此,操作数据库必须要有数据库连接
在这里插入图片描述

  • 定义Schema和Model
    Schema组成Model,Model对应mongodb中的文档
    比如,我们数据库中需要保存两种模型,分别是用户和新闻
// user
{
    
    
  loginId: "xxxx", // 登录账号
  loginPwd: "xxxx", // 登录密码
  name: "xxxx", // 用户姓名
  age: 18, // 用户年龄
  role: "xxx" // 用户角色:管理员、普通用户、VIP 之一
}

// news
{
    
    
  title: "", // 新闻标题
  content: "", // 新闻内容
  pubDate: xxx, // 新闻发布日期
  channel: "", // 新闻频道
  link: "" // 新闻原始链接地址
}

我们需要先对其进行Schema定义,然后通过Schema定义模型
在这里插入图片描述

  • 用户
var userSchema = new mongoose.Schema({
    
    
  loginId: {
    
    
    type: String,
    required: true,//必填
    unique: true,//属性值唯一
    trim: true,//写入数据时,会自动的去掉首尾空格
    minlength: 3,//约束,字符串的最小长度为3
    maxlength: 18,//约束,字符串的最大长度为18
  },
  loginPwd: {
    
    
    type: String,
    required: true,
    trim: true,
    minlength: 6,
    maxlength: 18,
    select: false,//后续对用户进行查询的时候,默认情况下,不要查询密码
  },
  name: {
    
    
    type: String,
    required: true,
    trim: true,
    minlength: 2,
    maxlength: 10,
  },
  age: {
    
    
    type: Number,
    required: true,
    min: 1,//年龄的最小值为1
    max: 100,//年龄的最大值为100
  },
  role: {
    
    
    type: String,
    required: true,
    trim: true,
    enum: ["管理员", "普通用户", "VIP"],//用户角色是一个字符串,该字符串的取值必须是"管理员", "普通用户", "VIP"中的一个
  },
});

var User = mongoose.model("User", userSchema);//定义一个模型
//操作数据库时,使用模型进行操作User News(如增加删除查询都需要用到)
  • 新闻
var newsSchema = new mongoose.Schema({
    
    
  title: {
    
    
    type: String,
    required: true,
    trim: true,
  },
  content: {
    
    
    type: String,
    trim: true,
  },
  pubDate: {
    
    
    type: Date,
    required: true,
    default: Date.now,//默认值,可以使一个值,也可以是一个函数(函数的返回值作为默认值)
  },
  channel: {
    
    
    type: String,
    required: true,
  },
  link: {
    
    
    type: String,
    required: true,
  },
});

var News = mongoose.model("News", newsSchema);

CRUD
CRUD(Create, Retrieve, Update, Delete)简称为增删改查,是对数据库最基本的操作

  • 新增

模型.create(对象)

对象可以是单个对象或者是数组
该操作是异步的,可以使用回调函数或ES7的await关键字得到新增的结果
新增的对象会自动添加两个属性:

  • _id:自动生成,用于表示文档的主键,全球唯一
  • __v:自动生成,用于表示文档的版本,内部维护,不需要开发者处理
  • 查询

模型.findById(id); // 根据id字符串查询单个文档,若查找不到,则返回null
模型.find(filter, [projection], [options]); // 根据条件、投影、配置 进行查询

filter

  • 过滤条件对象
  • api极其丰富
  • 下面是一些常见filter写法
// 查询所有 channel="财经焦点" 的新闻
{
    
    
  channel: "财经焦点" 
}

// 查询所有 channel="财经焦点" 并且 title 包含 中国 的新闻
{
    
    
  channel: "财经焦点", 
 	title: /中国/  
}

// 查询所有 channel="财经焦点" 或者 title 包含 中国 的新闻
{
    
    
  $or: [
    {
    
    
      channel: "财经焦点",
    },
    {
    
    
      title: /中国/,
    },
  ],
}
  
// 查询所有 发布日期 大于等于 昨天此时 的新闻
// $gt 大于  $gte 大于等于  $lt 小于 $lte 小于等于   $ne 不等于 
// $in 其值在某个数组中  $nin 其值不在某个数组中
{
    
    
  pubDate: {
    
    
    $gte: Date.now() - 3600 * 24 * 1000,
  }
}

projection

  • 可选参数
  • 对象
  • 一些额外的配置
// 跳过结果中的 5 条数据,取 6 条
{
    
    
  skip: 5,
  limit: 6,
}
  
// 按照发布日期的降序排序
{
    
    
  sort: "-pubDate"
}

模型.count(filter); // 获取指定条件的数量

  • 更新

模型.updateOne(filter, doc); // 更新单个文档
模型.updateMany(filter, doc); // 更新多个文档

filter:条件,和查询中的filter含义和用法完全一致
doc:新的文档,新文档中的属性会覆盖旧文档中的对应字段

  • 删除

模型.deleteOne(filter); // 删除单个文档
模型.deleteMany(filter); // 删除多个文档

实例:
先创建一个文件夹
在这里插入图片描述
连接数据库代码:
在这里插入图片描述
项目代码:
在这里插入图片描述
归纳代码:
在这里插入图片描述
添加数据

  • 第一种写法
    在这里插入图片描述
  • 第二种写法(ES7写法)
    在这里插入图片描述

在这里插入图片描述
从json文件中添加数据
json文件代码
在这里插入图片描述
添加数据代码
在这里插入图片描述

  • 查询代码:
  • 查询单个
//查询单个
async function test() {
    
    
    var result = await models.User.findById("5ecc9f2496fd6f0f20d5498f");
    console.log(result);
}
test();

在这里插入图片描述

  • 条件查询
var models = require("./models"); //导出
//查询单个
async function test() {
    
    
    var result = await models.News.find({
    
    //查询channel=财经焦点的数据
        channel: "财经焦点",
    });
    console.log(result);
}
test();
var models = require("./models"); //导出
//查询单个
async function test() {
    
    
    var result = await models.News.find({
    
     //查询的时间大于等于这个时间
        pubDate: {
    
    
            $gte: Date.now() - 3600 * 24 * 1000,
        }
    });
    console.log(result);
}
test();

在这里插入图片描述

第二个参数

var models = require("./models"); //导出
//查询单个
async function test() {
    
    
    var result = await models.News.find({
    
     //查询channel=财经焦点的数据
        channel: "财经焦点",
    }, "title pubDate");//只显示title pubDate这两行的数据
    console.log(result);
}

test();

在这里插入图片描述

第三个参数

var models = require("./models"); //导出
//查询单个
async function test() {
    
    
    var result = await models.News.find({
    
     //查询channel=财经焦点的数据
        channel: "财经焦点",
    }, "title pubDate", {
    
     //跳过0个,取两个数
        skip: 0,
        limit: 2,
    }); //只显示title pubDate这两行的数据
    console.log(result);
}

test();

在这里插入图片描述
获取最新消息

var models = require("./models"); //导出
//查询单个
//获得最新发布的新闻(1条)
async function test() {
    
    
    var result = await models.News.find({
    
     //查询channel=财经焦点的数据

    }, "title pubDate", {
    
     //用降序
        sort: "-pubDate",
        limit: 1, //取第一条

    }); //只显示title pubDate这两行的数据
    console.log(result);
}

test();

在这里插入图片描述

  • 第三个查询,查数量
var models = require("./models"); //导出
async function test() {
    
    
    var result = await models.News.countDocuments();
    console.log(result);
}

test();

//查指定条件的

在这里插入图片描述

  • 更新数据
var models = require("./models"); //导出
async function test() {
    
    
    //吧id等于5ecc9ff46d5c662c28034ba9的文档进行更新
    //用{channel:"财经焦点"}覆盖旧文档
    var result = await models.News.updateOne({
    
    
        _id: "5ecc9ff46d5c662c28034ba9",
    }, {
    
    
        channel: "财经焦点",
    })
    console.log(result);
}

test();

在这里插入图片描述

  • 删除数据

第三天

http协议

image-20200526121029435

客户端要连接 服务器,需要使用一个url地址来定位服务器,该url地址的格式为:

protocal://hostname:port/path?query#hash

例如:http://localhost:9527/news?page=1&limit=10#2

他们各个部分分别是:

  • protocalhttp //协议
  • hostname: localhost //主机名,localhost是本机的意思
  • port: 9527,如果没有写端口号,默认为80
  • path: /news //表示我想获取新闻
  • query: ?page=1&limit=10,表示有两个信息传递过来{page:1, limit:10}
  • hash2,hash一般用作锚链接,服务器一般不需要这个信息

如果url地址成功的找到了服务器,客户端会组装一个特别的消息格式发送给服务器,称之为请求

请求内容格式示例:

GET /news?page=1&limit=10#2 HTTP/1.1
Host: localhost:9527
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...
Connection: keep-alive
Accept-Encoding: gzip, deflate

<没有消息体>

服务器收到客户端的消息后,会处理该消息,然后返回给客户端一个消息,称之为响应

响应内容格式示例:

HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
Server: Express
Cache-Control: no-cache

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>新闻页面</h1>
</body>
</html>

搭建web服务器

web服务器的基本功能:

  1. 能够监听计算机的某个端口
  2. 当客户端有请求发送过来时,能够做出相应的处理——处理请求

各种后端技术均可以搭建web服务器,同一种后端技术,搭建web服务器的方式也有多种

node环境中,搭建web服务器的方式有:

  1. 使用nethttp内置模块进行搭建
  2. 使用第三方库,如:expresskoa2egg.jsnest.js

安装

安装express

npm i express

安装nodemon

npm i -D nodemon

安装postman

创建服务器并监听端口

var express = require("express"); // 导入express
var app = express(); // 创建一个web服务器
app.listen(9527, function(){
    
     // 监听端口
  console.log("server listening on 9527");
})

处理请求

// 当请求方法为GET,请求的path为/news时,会交给指定的函数处理,指定的函数称之为 处理函数
app.get("/news", function(req, res){
    
    
  // req 请求对象,可以获取请求传递过来的信息
  // res 响应对象,通过该对象可以控制响应的消息内容
})
// 当请求方法为POST,请求的path为/login时,会交给指定的函数处理
app.post("/login", function(req, res){
    
    
  
})
// 当请求方法为GET,请求的path为/news/ooo/xxx时,会交给指定的函数处理,并把ooo对应到year,把xxx对应到month
app.get("/news/:year/:month", function(req, res){
    
    
  console.log("req.path", req.path);//获取的格式,如下
})

//要怎么运行,在终端输入npm start
  • req对象,表示请求对象(request)

    • path:获取请求的path
    • method:获取请求行中的请求方法。大部分使用,浏览器都会发出GET请求,GET请求一般不会附带请求体,所有的信息都在请求行和请求头中
    • query:获取请求行中的query
    • headers:获取请求头中的键值对
    • params:获取动态路径部分对应的值
  • res对象,表示响应对象(response)

    • send(data):设置响应体,并结束响应

    • header(name, value),设置响应头中的键值对,某些键值对会影响到浏览器的行为

      • Content-Type:告诉浏览器,我给你的响应体是一个什么类型的数据,这个字段会触发浏览器的不同行为
        • text/html:浏览器会当做页面渲染
        • image/png:浏览器会当做png图片渲染
        • application/javascript:浏览器会当做js代码
        • text/css:浏览器会当做css代码
      • Locatioin:见302消息码
    • type(ext),该函数可以快捷的设置Content-Type

      res.type('.html')
      // => 'text/html'
      res.type('html')
      // => 'text/html'
      res.type('json')
      // => 'application/json'
      res.type('application/json')
      // => 'application/json'
      res.type('png')
      // => 'image/png'
      
    • status(code),设置响应行中的消息码,不同的消息码会影响到浏览器的行为

      • 200:正常响应
      • 404:资源不存在
      • 302:资源已转移到另外一个地址,另一个地址在响应头的Location

练习

开发一个静态资源服务器

具体要求:编写一个请求处理函数,该函数能够根据请求的路径响应某个目录中对应的文件,并把文件内容发送给客户端

请求:/
响应文件内容:项目路径/public/index.html

请求:/index.html
响应文件内容:项目路径/public/index.html

请求:/js/index.js
响应文件内容:项目路径/public/js/index.js

可能会用到的函数:

  • path.resolve

  • path.extname(filename):获取某个路径的后缀名

  • fs.promises.stat(filename):异步函数,需要等待,获取某个文件的状态信息

    • 若文件不存在,报错

    • 返回一个状态信息对象 stats

      stats.isDirectory(); // 是否是一个目录
      stats.isFile(); // 是否是一个文件
      
  • fs.promises.readFile(filename):异步函数,需要等待,获取某个文件的内容

答案:
在这里插入图片描述

var express = require("express"); // 导入express
var app = express(); // 创建一个web服务器
var path = require("path");
var fs = require("fs");
/*
/   ->   public/index.html
/index.html   ->   public/index.html
/css/a.css    ->   public/css/a.css
/js/a.js    ->   404
*/
// *表示匹配所有请求

async function handler(req, res) {
    
    
    //1. 根据请求路径,得到文件路径
    // req.path   /news     public/news
    var filename = path.resolve(__dirname, "public" + req.path);
    //2. 获取文件的状态信息
    try {
    
    
        var stat = await fs.promises.stat(filename);
        if (stat.isFile()) {
    
    
            // 是一个正常文件
            var content = await fs.promises.readFile(filename); //读取文件内容
            // 设置响应的消息格式
            var extname = path.extname(filename); //获取文件扩展名
            res.type(extname);
            res.send(content);
        } else {
    
    
            // 是一个目录
            console.log("不考虑这种情况");
        }
    } catch {
    
    
        // 文件不存在
        // 响应404
        res.status(404);
        res.send("资源不存在");
    }
}
app.get("*", handler);

app.listen(9527, function() {
    
    
    // 监听端口
    console.log("server listening on 9527");
});

第四天

express中间件模型

在某些场景中,对请求的处理可能会经过多个步骤,比如:日志记录、安全验证、权限验证、业务处理,为了分割这些不同的处理,express提供了中间件的模型

中间件示意图

每个中间件本质上就是一个处理函数,通过app.use注册

app.use(function(req, res, next){
    
    
  console.log("中间件1的处理");
  next(); //交给下一个匹配的中间件
})
// 注意:use中的路径匹配的是基路径,下面的处理函数可以匹配所有以 /news 开头的路径
app.use("/news", function(req, res, next){
    
    
  console.log("中间件2的处理");
	next(); //交给下一个中间件
})

app.use("/login", function(req, res){
    
    
  console.log("中间件3的处理,不再往后移交");
})

当我们访问/news/123时,请求会依次交给中间件1中间件2

当我们访问/login/xxxx时,请求会依次交给中间件1中间件3

这样一来,我们就可以把一些通用的逻辑写成中间件,使用app.use注册即可
在这里插入图片描述

常用中间件

中间件就是一个函数

express给我们制作了一些常用的中间件,通过注册这些中间件,可以轻松实现一些通用功能

express.static

// 该函数返回一个中间件
// 它将指定的目录作为静态资源目录
// 当访问服务器时,该中间件会通过 path 对应该目录中的文件
// 如果能够找到文件,则直接响应文件内容,不再向后移交

// 若无法找到文件,向后移交
express.static(dir);

使用示例:

app.use(express.static(path.resolve(__dirname, "public")))
//这行代码运行成功后就不会运行下面的代码了

例子:

var express = require("express"); // 导入express
var app = express(); // 创建一个web服务器
var path = require("path"); //获取绝对路径

// 搭建一个静态资源服务器//就是资源会从这里去找
app.use(express.static(path.resolve(__dirname, "public")));


// Content-Type: application/x-www-form-urlencoded
app.use(express.urlencoded({
    
     extended: true }));
// Content-Type: application/json
app.use(express.json());



// 路由中间件
app.use("/api/user", require("./routes/user"));
app.use("/api/news", require("./routes/news"));
app.listen(9527, function() {
    
    
    // 监听端口
    console.log("server listening on 9527");
});

上面有查询方法,前提是要有这个html界面
在这里插入图片描述

express.urlencoded

// 该函数返回一个中间件
// 如果它发现请求头中的 content-type 的值是 application/x-www-form-urlencoded
// 则会把请求体中的内容解析为一个对象,保存到 req.body 中,然后向后移交
// 否则,直接向后移交
express.urlencoded();

使用示例:

// 使用配置 {extended: true},避免报出警告
app.use(express.urlencoded({
    
    extended: true}));

保存文件
在这里插入图片描述

express.json

// 该函数返回一个中间件
// 如果它发现请求头中的 content-type 的值是 application/json
// 则会把请求体中的内容解析为一个对象,保存到 req.body 中,然后向后移交
// 否则,直接向后移交
express.json();

使用示例:

app.use(express.json());

保存文件
在这里插入图片描述

express.Router

// 该函数返回一个中间件,称之为路由中间件
var router = express.Router();

// 匹配 GET 基路径/
router.get("/", function(req, res){
    
    
  
})
// 匹配 GET 基路径/a
router.get("/a", function(req, res){
    
    
  
})
// 匹配 POST 基路径/
router.post("/", function(req, res){
    
    
  
})
// 当基路径为 /api/user 时,交给该路由处理
// 如果路由没有命中,则它会自动往后移交
app.use("/api/user", router);

使用路由中间件处理请求更加有助于模块拆分
在这里插入图片描述
在这里插入图片描述

服务器的职责

在不同的场景下,服务器有着不同的职责,极其灵活

很多的中小型系统,一个服务器往往承担着两个职责:

  • 提供静态资源
  • 提供api接口
image-20200527131821014

我们可以来看一个经典的场景,以梳理服务器和浏览器之间的交互

image-20200527132657593

练习

  1. express搭建静态资源服务器,并将给予的静态页面目录中的内容作为静态资源放到服务器中
  2. express路由开发api接口,规则如下
    1. 针对用户的操作
      1. 登录,POST /api/user/login,消息体中传递账号和密码
      2. 注册,POST /api/user/reg,消息体中传递注册信息,新注册的用户必定为普通用户
    2. 针对新闻的操作
      1. 分页获取新闻,GET /api/newsquery可能传递pagelimit
  3. 开发静态资源中的/js/practice.js,想想静态资源中的js是在哪一端运行的,然后补全该文件中下面的函数:
    1. getNews
    2. reg
    3. login

登录注册代码:

// 专门处理针对用户的操作
var express = require("express");
var services = require("../services");
var router = express.Router();

router.post("/login", async function (req, res) {
    
    
  var result = await services.userService.login(
    req.body.loginId,
    req.body.loginPwd
  );
  if (result) {
    
    
    res.send(result);
  } else {
    
    
    res.send({
    
    
      err: "账号和密码错误",
    });
  }
});

router.post("/reg", async function (req, res) {
    
    
  req.body.role = "普通用户";
  try {
    
    
    var result = await services.userService.reg(req.body);
    res.send(result);
  } catch (err) {
    
    
    res.send({
    
    
      err: err.message,
    });
  }
});

module.exports = router; // 导出路由中间件

2.新闻代码:

// 针对新闻的请求
var express = require("express");
var router = express.Router();
var services = require("../services");
router.get("/", async function (req, res) {
    
    
  var page = +req.query.page || 1; // 如果没有传递page,默认1
  var limit = +req.query.limit || 10; //如果没有传递limit,默认10
  var result = await services.newsService.getNews(page, limit, "");
  res.send(result);
});

module.exports = router;// 导出路由中间件

猜你喜欢

转载自blog.csdn.net/weixin_44931166/article/details/106325412