nodejs后端相关知识总结

2023-11-19

1.koa

koa执行逻辑代码:

app.use(async (ctx, next) => {
    await next();
    ctx.response.type = 'text/html';
    ctx.response.body = '<h1>Hello, koa2!</h1>';
});

每收到一个http请求,koa就会调用通过app.use()注册的async函数,并传入ctxnext参数。

我们可以对ctx操作,并设置返回内容。但是为什么要调用await next()

原因是koa把很多async函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用await next()来调用下一个async函数。我们把每个async函数称为middleware,这些middleware可以组合起来,完成很多有用的功能。

middleware的顺序很重要,也就是调用app.use()的顺序决定了middleware的顺序。

此外,如果一个middleware没有调用await next(),会怎么办?答案是后续的middleware将不再执行了。这种情况也很常见,例如,一个检测用户权限的middleware可以决定是否继续处理请求,还是直接返回403错误:

app.use(async (ctx, next) => {
    if (await checkUserPermission(ctx)) {
        await next();
    } else {
        ctx.response.status = 403;
    }
});

最后注意ctx对象有一些简写的方法,例如ctx.url相当于ctx.request.urlctx.type相当于ctx.response.type

2.koa-router

为了处理URL,需要引入koa-router这个middleware,让它负责处理URL映射。 

 使用koa-router来处理URL:

const Koa = require('koa');

// 注意require('koa-router')返回的是函数:
const router = require('koa-router')();

const app = new Koa();

// log request URL:
app.use(async (ctx, next) => {
    console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);
    await next();
});

// add url-route:
router.get('/hello/:name', async (ctx, next) => {
    var name = ctx.params.name;
    ctx.response.body = `<h1>Hello, ${name}!</h1>`;
});

router.get('/', async (ctx, next) => {
    ctx.response.body = '<h1>Index</h1>';
});

// add router middleware:
app.use(router.routes());

app.listen(3000);
console.log('app started at port 3000...');

注意导入koa-router的语句最后的()是函数调用:

const router = require('koa-router')();

使用router.get('/path', async fn)来注册一个GET请求。可以在请求路径中使用带变量的/hello/:name,变量可以通过ctx.params.name访问。

3.koa-bodyparser处理post请求

router.get('/path', async fn)处理的是get请求。如果要处理post请求,可以用router.post('/path', async fn)

用post请求处理URL时,我们会遇到一个问题:post请求通常会发送一个表单,或者JSON,它作为request的body发送,但无论是Node.js提供的原始request对象,还是koa提供的request对象,都不提供解析request的body的功能!

所以,我们又需要引入koa-bodyparser来解析原始request请求,然后,把解析后的参数,绑定到ctx.request.body中。

引入koa-bodyparser

const bodyParser = require('koa-bodyparser');

在合适的位置加上:

app.use(bodyParser());

由于middleware的顺序很重要,这个koa-bodyparser必须在router之前被注册到app对象上。

现在我们就可以处理post请求了。写一个简单的登录表单:

router.get('/', async (ctx, next) => {
    ctx.response.body = `<h1>Index</h1>
        <form action="/signin" method="post">
            <p>Name: <input name="name" value="koa"></p>
            <p>Password: <input name="password" type="password"></p>
            <p><input type="submit" value="Submit"></p>
        </form>`;
});

router.post('/signin', async (ctx, next) => {
    var
        name = ctx.request.body.name || '',
        password = ctx.request.body.password || '';
    console.log(`signin with name: ${name}, password: ${password}`);
    if (name === 'koa' && password === '12345') {
        ctx.response.body = `<h1>Welcome, ${name}!</h1>`;
    } else {
        ctx.response.body = `<h1>Login failed!</h1>
        <p><a href="/">Try again</a></p>`;
    }
});

注意到我们用var name = ctx.request.body.name || ''拿到表单的name字段,如果该字段不存在,默认值设置为''

类似的,put、delete、head请求也可以由router处理。

4.Nunjucks渲染模板

Nunjucks是一个模板引擎,即基于模板配合数据构造出字符串输出的一个组件,以下为一个模板引擎的例子:

function examResult (data) {
    return `${data.name}同学一年级期末考试语文${data.chinese}分,数学${data.math}分,位于年级第${data.ranking}名。`
}

如果我们输入数据如下:

examResult({
    name: '小明',
    chinese: 78,
    math: 87,
    ranking: 999
});

该模板引擎把模板字符串里面对应的变量替换以后,就可以得到以下输出:

小明同学一年级期末考试语文78分,数学87分,位于年级第999名。

模板引擎最常见的输出就是输出网页,也就是HTML文本。当然,也可以输出任意格式的文本,比如Text,XML,Markdown等等。

app.js中编写Nunjucks的函数render如下:

const nunjucks = require('nunjucks');

function createEnv(path, opts) {
    var
        autoescape = opts.autoescape === undefined ? true : opts.autoescape,
        noCache = opts.noCache || false,
        watch = opts.watch || false,
        throwOnUndefined = opts.throwOnUndefined || false,
        env = new nunjucks.Environment(
            new nunjucks.FileSystemLoader('views', {
                noCache: noCache,
                watch: watch,
            }), {
                autoescape: autoescape,
                throwOnUndefined: throwOnUndefined
            });
    if (opts.filters) {
        for (var f in opts.filters) {
            env.addFilter(f, opts.filters[f]);
        }
    }
    return env;
}

var env = createEnv('views', {
    watch: true,
    filters: {
        hex: function (n) {
            return '0x' + n.toString(16);
        }
    }
});

变量env就表示Nunjucks模板引擎对象,它有一个render(view, model)方法,正好传入viewmodel两个参数,并返回字符串。

创建env需要的参数可以查看文档获知。我们用autoescape = opts.autoescape && true这样的代码给每个参数加上默认值,最后使用new nunjucks.FileSystemLoader('views')创建一个文件系统加载器,从views目录读取模板。

我们编写一个hello.html模板文件,放到views目录下,内容如下:

<h1>Hello {{ name }}</h1>

然后,我们就可以用下面的代码来渲染这个模板:

var s = env.render('hello.html', { name: '小明' });
console.log(s);

获得输出如下:

<h1>Hello 小明</h1>

此外,可以使用Nunjucks提供的功能强大的tag,编写条件判断、循环等功能,例如:

<!-- 循环输出名字 -->
<body>
    <h3>Fruits List</h3>
    {% for f in fruits %}
    <p>{{ f }}</p>
    {% endfor %}
</body>

Nunjucks模板引擎最强大的功能在于模板的继承。仔细观察各种网站可以发现,网站的结构实际上是类似的,头部、尾部都是固定格式,只有中间页面部分内容不同。如果每个模板都重复头尾,一旦要修改头部或尾部,那就需要改动所有模板。

更好的方式是使用继承。先定义一个基本的网页框架base.html

<html><body>
{% block header %} <h3>Unnamed</h3> {% endblock %}
{% block body %} <div>No body</div> {% endblock %}
{% block footer %} <div>copyright</div> {% endblock %}
</body>

base.html定义了三个可编辑的块,分别命名为headerbodyfooter。子模板可以有选择地对块进行重新定义:

{% extends 'base.html' %}

{% block header %}<h1>{{ header }}</h1>{% endblock %}

{% block body %}<p>{{ body }}</p>{% endblock %}

然后,我们对子模板进行渲染:

console.log(env.render('extend.html', {
    header: 'Hello',
    body: 'bla bla bla...'
}));

输出HTML如下:

<html><body>
<h1>Hello</h1>
<p>bla bla bla...</p>
<div>copyright</div> <-- footer没有重定义,所以仍使用父模板的内容
</body>

5.使用MVC

当用户通过浏览器请求一个URL时,koa将调用某个异步函数处理该URL。在这个异步函数内部,我们用一行代码:

ctx.render('home.html', { name: 'Michael' });

通过Nunjucks把数据用指定的模板渲染成HTML,然后输出给浏览器,用户就可以看到渲染后的页面了:

mvc

这就是传说中的MVC:Model-View-Controller,中文名“模型-视图-控制器”。

异步函数是C:Controller,Controller负责业务逻辑,比如检查用户名是否存在,取出用户信息等等;

包含变量{{ name }}的模板就是V:View,View负责显示逻辑,通过简单地替换一些变量,View最终输出的就是用户看到的HTML。

MVC中的Model在哪?Model是用来传给View的,这样View在替换变量的时候,就可以从Model中取出相应的数据。

上面的例子中,Model就是一个JavaScript对象:

{ name: 'Michael' }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nodejs后端相关知识总结 的相关文章

  • Vue项目中 vue-waterfall-easy 瀑布流框架使用

    1 Installation 安装 进入到项目当前文件夹 执行命令 npm install vue waterfall easy save 2 引入vue waterfall easy 2 1 main js中引入 import vueWa
  • MVC MVP MVVM

    参考MVC MVP MVVM的区别 前端面试标准答案 知乎 zhihu com 总结 MVC将应用抽象为数据层 Model 视图层 View 逻辑层 controller 降低了项目耦合 但MVC并未限制数据流 Model和View之间可以
  • Android 获取系统中软件的信息

    得到手机中所有的应用程序信息 return public List
  • 【100%通过率 】华为OD真题c++/python 【羊、狼、农夫过河】【 2022 Q4

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 羊 狼 农夫都在岸边 农夫有一艘容量固定的船 要求求出不损失羊情况下将全部羊和狼运到对岸需要的次数 农夫在或农夫离开后羊的数量大于狼的数量时狼不
  • css3动画属性解析:【transition-过渡】

    一 css3动画之 transition 语法 简写方式 transition property duration timing function delay div transition all 1s ease in out 2s 上面这
  • PWM模块:边沿对齐PWM和中心对齐PWM

    PWM模块 边沿对齐PWM和中心对齐PWM 当PWM 时基工作在自由运行模式时 模块产生边沿对齐的PWM 信号 给定PWM 通道的输出1 边沿对齐模式 信号的周期由装入PTPER 的值指定 其占空比由相应的PDCx 寄存器指定 参见图15
  • ChatGPT热度“狂飙”,OceanBase也去找它唠了唠

    最近互联网的关键字 非 ChatGPT 莫属 就是这个小东西 集唠嗑 提问 答疑 科普 写作于一体 让我看看哪个孤独的打工人 还没和 ChatGPT 聊上一聊 有人说 ChatGPT 这么智能 或将取代人类的工作 OceanBase 的小编
  • c/c++资源汇总

    Visual C 视频技术方案宝典 pdf http www t00y com file 17628500 Windows 图形编程 pdf http www t00y com file 17628502 Windows程序设计 第2版 p
  • 100天精通Python(数据分析篇)——第52天:numpy模块完结篇

    文章目录 一 拷贝 1 赋值 2 视图 3 副本 4 注意点copy和view 二 numpy常用方法 1 小技巧 2 生成随机数 三 numpy中的nan和inf 一 拷贝 1 赋值 简单的赋值不会创建数组对象的副本 相反 它使用原始数组
  • Unity 使用Photon Server 联网开发(二)游戏同步+房间列表

    photon联机的配置 直接去官网下载Pun的资源包导入项目 设置PhotonServerSettings配置文件 配置appid 通讯协议 服务器地址 端口号 服务器地址可以配置成自己本地服务器 云服务器 直接使用photon服务器 也可
  • 吕聪贤SwiSHmax中文视频教程打包下载(连接已失效)

    教程介绍 SwiSHmax是Flash编辑工具 SwiSHzone家族的新成员 假如您想要不使用Flash来制作强大或令人惊叹的动画 SwiSHmax是您最佳的选择 SwiSHmax操作方便 您将可轻易的在短时间内制作出复杂的文本 图像 图
  • HashTable HashMap ConcurrentHashMap 的介绍以及区别

    目录 今日良言 投资自己才是最好的投资 一 HashMap 二 HashTable 三 ConcurrentHashMap 四 三者的区别 今日良言 投资自己才是最好的投资 这篇博客主要介绍的是 HashTable HashMap Conc
  • 计算机图形学 3D渲染 笔记(一)

    1 坐标系 大多数计算机屏幕采用的坐标系是以左上角为原点 水平 右 为x轴 纵向 下 为y轴 3D图形学习中通常使用另一种坐标系 即 正中心为原点 水平 右 为x轴 纵向 上 为y轴 当前者坐标系转化到后者 需要进行简单的转化 Sx Sy为
  • IDEA2021.2安装与配置(持续更新)

    IDEA2021 2安装与配置 持续更新 一 下载 二 安装 三 配置 3 1 配置全局生效 3 2 首次启动 3 3 激活 3 4 字体 字体大小 3 5 配色方案 3 6 注解生效 3 7 自动导包移包 3 8 自动补全快捷键 3 9
  • vue-nginx刷新404问题

    文章目录 1 背景介绍 2 问题描述 2 1 问题一 2 2 问题二 3 原因分析 3 1 问题一 3 2 问题二 4 排查问题一原因 5 反思 6 nginx root与alias的使用 7 更优雅地解决vue网页浏览器刷新404 7 1
  • Mongodb——使用Mongodb对字段中字符串内容进行截取,并进行分组统计

    最近忙的厉害 除了发一发之前写的存货只能写一些简单的东西了 这里就简单分享下最近遇见针对数据进行指标统计遇见的问题 针对字段中某部分内容的指标统计 在使用mongodb进行指标统计的时候可能遇见下面的数据结构 1 id ObjectId 5
  • 短信备份到另一个手机android,旧手机的短信怎么转移到新手机上?三种方法总有一种适合你...

    手机短信一直以来都是我们和其他对象传输信息的工具 更是存储了大量重要的信息 如果我们更换手机需要保留下来这些短信该怎么办呢 有没有什么方法可以将这些短信转移到新手机中去 或者导出到电脑上进行保管呢 这里有三种方法 第一种方法用内存卡 可以打
  • C++仿函数

    1 仿函数的定义 仿函数简单说就是在类中定义的特殊函数 没有函数名 或者说函数名统一为 operation 或者可以认为是重载运算符 格式为 返回类型 operator 参数列表 定义了仿函数的对象 可以直接通过下面格式调用仿函数 对象名
  • 异步加载vue组件

    什么时候使用 组件较大 或者不是必用的 通常组件在script标签对中导入 而异步组件在component中使用 例如 components ForData gt import view Fordata
  • J2EE集合框架

    1 UML 二 集合的基本特点 list集合的特点 增删改查 有序 可重复 三 List集合的三种遍历方式 for foreath iterator 四 ArrayList LinkedList 的比较与分析 比较 1 ArrayList

随机推荐

  • 基于Matlab的灰狼算法优化LSTM风电功率预测

    基于Matlab的灰狼算法优化LSTM风电功率预测 随着可再生能源的快速发展 风能作为一种重要的清洁能源形式变得越来越受关注 风电功率预测在风电场的运营和调度中起着关键作用 然而 由于风速的不稳定性和不确定性 精确地预测风电功率仍然具有一定
  • SpringCloud Gateway:status: 503 error: Service Unavailable

    使用SpringCloud Gateway路由请求时 出现如下错误 yml配置如下 可能的一种原因是 yml配置了gateway discovery locator enabled true 此时gateway会使用负载均衡模式路由请求 但
  • Lim接口测试平台-接口测试功能详解

    一 接口测试 项目地址 Gitee Github 接口测试模块是整个Lim平台的核心 左侧是接口的模块树 右侧顶部是用例操作功能区 列表展示接口用例信息 文章目录 一 接口测试 二 维护接口用例 各步骤类型详解 1 执行步骤 1 接口步骤
  • Unity --- 触摸方法,以及灯光与烘培的使用

    触摸方法 1 首先触摸分为两大类 多点触摸和单点触摸 这两种方式的触摸通过下面这个触摸数来进行判断 当其等于1的时候 为单点触摸 当其大于1的时候为多点触摸 2 当我们在调用触摸方法的时候我们首先需要打开对应的多点 单点触摸 上面这个是开启
  • QObject的d_ptr成员——箭头符号的重载

    QObject中的d ptr是这样定义的 QScopedPointer
  • vscode cmake 编译32位程序

    vscode cmake 编译32位程序 为什么要用cmake vscode中的C C 插件直接支持的只是最简单的单文件编译 运行和调试 要管理大的项目 或者生成库 C C 插件不能直接支持 需要开发者利用vscode的task功能 结合脚
  • 【由浅入深】爬虫技术,值得收藏,来了解一下~

    爬虫技术 来了解一下 一 为什么需要爬虫技术 现在的互联网来说 包含着各种海量的信息 无孔不入 包罗万象 出于数据分析或产品需求 我们需要从某些网站 提取出我们感兴趣 有价值的内容 我们需要一种能自动获取网页内容并可以按照指定规则提取相应内
  • 关于两数交换的两种方法

    目录 前言 一 引入变量 这个方法也是最常用的方法 二 通过使用数学的方法相加或者相减从而得到两数运算 这种方法不常见 总结 前言 从键盘输入两个整数 并交换两位数字 这里小编用两种方法告诉大家 注意小编这里用的是VS2019 所以在代码的
  • STM32 --通用定时器输入捕获功能

    问题 开始的时候没有搞清楚 定时器时基 于 定时器溢出中断的概念 导致在计算频率的时候一直有问题 开始并没有怀疑是配置有问题 因为之前接触过定时器输入捕获功能 靠着自己的记忆配置了一下 认为 捕获功能 的定时是通过定时器设置的定时溢出频率来
  • 栈实现队列(继续细起来啊)

    生命不是要等待风暴过去 而是要学会在风暴中跳舞 卡莉尔 吉布朗目录 一 栈实现队列 二 使用两个栈实现队列的功能 1 在队列的结构体中创建两个栈 2 创建一个队列的结构体指针 3 myQueuePush入队列操作 4 myQueuePeek
  • SpringBoot项目实战(一)

    SpringBoot实战之系统架构 1 系统介绍 该实战项目 是一个B2C模式的职业技能在线教育系统 分为前台用户系统和后台运营平台 前台用户系统包括课程 问答 文章三大部分 后台运营平台包括会员管理 讲师管理 课程管理 文章资讯 统计分析
  • Gradle入门(二)尝试理解gralde编译项目

    前言 前面我们了解了如何通过groovy DSL转换为KTS 我也在尝试的证明可以看到源码和有代码提示对于入门的重要性 2022年11月12日 我发现最新的idea 有gradle的代码提示 点击也可以看到源码 学习Gradle还是建议整一
  • .NET框架和发展历史介绍

    NET框架知识 NET 框架是由微软开发的软件开发平台 其最主要的两个组成部分是公共语言运行时 CLR 和框架类库 FCL 基础类库 BCL 是框架类库的一个子集 NET框架的主要结构如下图所示 1 操作系统 最下层的无疑就是操作系统了 2
  • Linux内核之pid为0和pid为1【转】

    转自 https blog csdn net jingyilin2008 article details 7815508 ops request misc 257B 2522request 255Fid 2522 253A 25221592
  • 【Linux】Mint20.3系统安装Anaconda环境

    Anaconda是非常方便的python开发IDE环境 其中不仅包含了很多常用python库还有Spyder运行环境 Mint系统是近些年非常受欢迎的linux系统 易上手已操作特性使其普及非常快 本篇介绍在Mint20 3系统安装Anac
  • haclcon实现图像处理的傅里叶变换

    dev open file dialog read image default default Selection read image Image Selection mean image Image ImageMean 9 9 gaus
  • 多柱汉诺塔(Matrix上选做题)——递归与动态规划

    分析 对于三柱汉诺塔问题 我们已经熟知步骤数最优解为 2 i 1 2 i 1 2i 1 其中 i 为盘子个数 对于四柱以上的问题 我们将柱子分为三类 起点柱Start 辅助柱Buf
  • 侯捷系列:c++面向对象高级编程(上)

    文章目录 基于对象的程序设计 不带有指针成员变量的类 以复数类 Complex 为例 头文件的结构 访问级别 函数设计 内联函数 构造函数 常量成员函数 参数的值传递和引用传递 返回值的值传递和引用传递 友元 操作符重载 在类内声明 pub
  • sqli-labs (less-33)

    sqli labs less 33 进入33关 输入id 1 这里我们直接通过查看源代码查看这关是否也使用了GBK编码 可知确实使用了GBK编码 所以我们在单引号前面输入 df即可让单引号成功逃逸 http 127 0 0 1 sql1 L
  • nodejs后端相关知识总结

    1 koa koa执行逻辑代码 app use async ctx next gt await next ctx response type text html ctx response body h1 Hello koa2 h1 每收到一