前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >前端小白玩转koa(一)

前端小白玩转koa(一)

原创
作者头像
一起重学前端
修改2024-11-28 09:48:13
修改2024-11-28 09:48:13
14100
代码可运行
举报
运行总次数:0
代码可运行

好事发生

《腾讯IMA:AI智能工作台的革命性创新》

这里推荐一篇实用的文章:https://cloud.tencent.com/developer/article/2467267?shareByChannel=link

这篇文章深入解析了IMA Copilot的功能和应用场景,并通过与OpenAI Canvas的对比,帮助读者更好地理解不同AI写作工具的特点。对于关注AI技术在内容创作领域应用的读者而言,本文提供了有价值的参考。

前言

  • 记账小程序-云开发改node后端。 因云开发免费额度取消,刚好有一个服务器一直没有用+想重新学习node

node这么多框架,怎么选

Express

  • 简介:Express 是最流行的 Node.js web 应用框架之一。它基于 Node.js 的 HTTP 模块构建,提供了简洁的 API 用于构建 web 应用和 API。它的设计理念是简单、灵活,适合快速开发各种类型的 web 服务。
  • 特点
  • 简单易用:具有简洁的路由系统。例如,定义一个简单的 GET 请求路由可以这样写:
代码语言:javascript
代码运行次数:0
复制
     const express = require('express');
     const app = express();
     app.get('/', (req, res) => {
         res.send('Hello World!');
     });
     app.listen(3000, () => {
         console.log('Server running on port 3000');
     });
  • 中间件支持:可以方便地使用中间件来处理请求和响应。中间件函数可以在请求到达路由处理程序之前或之后执行,用于功能如日志记录、身份验证、数据解析等。例如,使用body - parser中间件来解析 POST 请求中的 JSON 数据:
代码语言:javascript
代码运行次数:0
复制
     const bodyParser = require('body - parser');
     app.use(bodyParser.json());
  • 高度可扩展:能够轻松地与各种数据库(如 MongoDB、MySQL 等)和模板引擎(如 EJS、Pug 等)集成,以构建功能丰富的 web 应用。

Koa

  • 作为 Express 的后继者,Koa 在异步操作处理和中间件机制上更加先进,通过使用 async/await 语法,让异步代码的编写更加直观,采用洋葱模型的中间件,使请求和响应的处理更加灵活。

NestJS

  • 简介:NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。它是基于 Type - Cript 构建的,充分利用了 TypeScript 的类型系统,使得代码更加健壮和易于维护。
  • 特点
  • 模块化架构:采用模块来组织代码,每个模块可以包含控制器、服务、提供者等组件。例如,定义一个简单的模块:
代码语言:typescript
复制
     import { Module } from '@nestjs/common';
     import { CatsController } from './cats.controller';
     import { CatsService } from './cats.service';
     @Module({
         controllers: [CatsController],
         providers: [CatsService],
     })
     export class CatsModule {}
  • 依赖注入:支持依赖注入,使得组件之间的耦合度降低。服务可以被注入到控制器中,便于代码的复用和测试。例如,在控制器中注入服务:
代码语言:typescript
复制
     import { Controller, Get } from '@nestjs/common';
     import { CatsService } from './cats.service';
     @Controller('cats')
     export class CatsController {
         constructor(private catsService: CatsService) {}
         @Get()
         async findAll() {
             return this.catsService.findAll();
         }
     }
  • 面向切面编程(AOP)支持:可以通过拦截器、过滤器等实现 AOP 功能,用于处理如日志记录、异常处理、性能监控等横切关注点。

LoopBack

  • 简介:LoopBack 是一个高度可扩展的 Node.js 框架,用于快速构建 RESTful API 和后端服务。它提供了强大的模型驱动的开发方式,能够自动生成 API 端点和数据库访问代码。
  • 特点
  • 模型驱动开发:通过定义数据模型,LoopBack 可以自动生成 CRUD(创建、读取、更新、删除)操作的 API。例如,定义一个简单的用户模型:
代码语言:javascript
代码运行次数:0
复制
     const {Model, DataSource} = require('loopback');
     const ds = new DataSource('memory');
     class User extends Model {}
     User.attachTo(ds);
     User.modelName = 'User';
  • 强大的连接器支持:可以连接到各种后端数据源,包括关系型数据库(如 MySQL、PostgreSQL)和非关系型数据库(如 MongoDB),以及其他外部服务(如 REST API、SOAP API)。例如,连接到 MySQL 数据库:
代码语言:javascript
代码运行次数:0
复制
     const {Connector, DataSource} = require('loopback');
     const mysqlConnector = Connector.extend('mysql', require('loopback - connector - mysql'));
     const ds = new DataSource('mysqlDS', {
         connector: mysqlConnector,
         host: 'localhost',
         port: 3306,
         database: 'mydb',
         username: 'user',
         password: 'password'
     });
  • 内置认证和授权机制:提供了用户认证和权限管理的功能,方便构建安全的 API。可以通过配置不同的认证策略(如基于 JWT、OAuth 等)来保护 API 端点。

Hapi

  • 简介:Hapi 是一个用于构建应用程序和服务的 Node.js 框架,它注重配置和插件系统,能够构建稳定、安全的 web 服务。
  • 特点
  • 配置驱动开发:使用配置对象来定义服务器设置、路由、插件等。例如,定义一个简单的路由配置:
代码语言:javascript
代码运行次数:0
复制
     const Hapi = require('hapi');
     const server = new Hapi.Server({
         port: 3000,
         host: 'localhost'
     });
     server.route({
         method: 'GET',
         path: '/',
         handler: (request, h) => {
             return 'Hello World';
         }
     });
  • 强大的插件系统:支持插件的开发和使用,插件可以用于扩展服务器的功能,如日志记录、缓存、认证等。可以方便地安装和卸载插件,并且插件之间相互独立,便于维护和升级。例如,使用hapi - vision插件来支持模板引擎:
代码语言:javascript
代码运行次数:0
复制
     const Inert = require('hapi - inert');
     const Vision = require('hapi - vision');
     const server = new Hapi.Server({...});
     await server.register([
         Inert,
         Vision
     ]);

为什么选Koa

为什么选Koa

  1. 异步操作处理优势
  2. 中间件机制的灵活性(洋葱模型)
  3. 轻量级和可定制性

缺点:轻量级过于灵活,缺少内置功能 想怎么写就怎么写。。。

ps:这里2年前用koa写的了,现在公司在使用NestJS,所有后续还会用NestJS重构一下,体验不同框架之间的差别和优劣、开发体验等等

开发微信小程序(记账小程序&h5通用api)

  • 为什么写记账功能,因为功能简单明了,容易上手。
  • 为什么要记账,你不理财财不理你
  • 记住普通人的第一笔启动资金就是攒钱攒出来的,大钱不是攒来的,小钱就是靠我们一点一点的积累才有机会去尝试更丰富的财富路径。不要相信哪些营销号消费陷阱:消费升级、提前消费、钱换一种方式留在身边、不花钱就不会赚钱,这就是裹挟消费绑架等等。 攒钱不是吝啬,可以投资自己提升自己
需求规划:
  1. 首页(banner、功能区、意见反馈入口)小程序登录授权&邮箱登录&手机号登录
  2. 添加/编辑账单(涉及收入/支出、消费类型、时间、金额、备注等等)api
  3. 新增自定义消费类型api
  4. 账单列表api
  5. 账单统计表格(类型分类、账本、时间筛选、收入/支出/总揽排行)
  6. 预设多记账本功能(待开发)
当时计划的TODOlist
  1. koa过于简单,需要二次开发
  2. 处理body传参 koa-bodyparser
  3. 通过文件动态创建路由 require-directory
  4. 请求参数检验 joi
  5. 全局错误处理
  6. jwt token 处理
  7. sequelize 操作数据库
  8. mysql
  9. redis 缓存
  10. 静态文件 koa-static
  11. 请求 axios
  12. 上传 koa-multer
  13. 本地热更新 nodemon
基于Koa二次开发

app.js

  1. 自动建标表
  2. 全局错误处理
  3. 静态资源
  4. 异步 Promise

今天先讲讲全局错误处理和异步 Promise

InitManager.initCore(app)

代码语言:js
复制
require('module-alias/register')

const Koa = require('koa');
const path = require('path');
const bodyParser = require('koa-bodyparser');
const static = require('koa-static');

const catchError = require('@middlewares/exception');
const InitManager = require('@core/init');

// 自动建标表
require('@models/index');

const app = new Koa();

// 全局错误处理
app.use(catchError);
// 使用ctx.body解析中间件 ctx.request.body
app.use(bodyParser());
// 静态资源
app.use(static(path.join(__dirname, './static')))
// 注册 中间键 上下文ctx 洋葱模型

// 异步 Promise
InitManager.initCore(app);

app.listen(3000, () => {
    console.log('启动 3000')
});
全局错误处理

洋葱模型在这里就不多赘述了,后面有机会单独出一篇文章,这里先应用

代码语言:js
复制
const catchError = require('@middlewares/exception');
const app = new Koa();

// 全局错误处理
app.use(catchError);

catchError

middlewares/exception.js

统一处理错误信息 msg、errorCode、request等等 这里还可以加上traceId 请求唯一值查询日志等等

代码语言:js
复制
const { HttpException } = require('../core/http-exception')

const catchError = async (ctx, next) => {
    try {
        await next();
    } catch (error) {
        const isHttpException = error instanceof HttpException;
        const isDev = global.config.environment === 'dev';

        if (isDev && !isHttpException) {
            throw error;
        }

        if (error instanceof HttpException) {
            const { msg, errorCode, code } = error;

            ctx.body = {
                msg: msg,
                error_code: errorCode,
                request: `${ctx.method} ${ctx.path}`
            };
            ctx.status = code;
        } else {

            ctx.body = {
                msg: 'we made a mistake',
                error_code: 999,
                request: `${ctx.method} ${ctx.path}`
            };
            ctx.status = 500;
        }
    }
}

module.exports = catchError;

core/http-exception

这个构造函数的目的是创建一个特定的错误对象,用于在应用程序中表示资源未找到的情况。通过继承 HttpException,它可以与其他 HTTP 异常类一起使用,提供统一的错误处理机制。

代码语言:js
复制
class HttpException extends Error{
    constructor(msg = '服务器异常', errorCode = 10000, code = 400) {
        super();
        this.errorCode = errorCode;
        this.code = code;
        this.msg = msg;
    }
}

class ParameterException extends HttpException {
    constructor(msg, errorCode) {
        super();
        this.code = 400;
        this.msg = msg || '参数错误';
        this.errorCode = errorCode || 10000;
    }
}

class Success extends HttpException {
    constructor(msg, errorCode) {
        super();
        this.code = 200;
        this.msg = msg || 'ok';
        this.errorCode = errorCode || 0;
    }
}

class NotFound extends HttpException{
    constructor(msg, errorCode) {
        super();
        this.msg = msg || '资源未找到';
        this.errorCode = errorCode || 10000;
        this.code = 404;
    }
}

class AuthFailed extends HttpException{
    constructor(msg, errorCode) {
        super();
        this.msg = msg || '授权失败';
        this.errorCode = errorCode || 10004;
        this.code = 401;
    }
}

class Forbidden extends HttpException {
    constructor(msg, errorCode) {
        super();
        this.msg = msg || '禁止访问';
        this.errorCode = errorCode || 10006;
        this.code = 403;
    }
}

module.exports = {
    HttpException,
    ParameterException,
    Success,
    NotFound,
    AuthFailed,
    Forbidden,
};
初始化initCore

init.js

  • 读取配置(服务&小程序appid等等信息s)
  • 基于require-directory 通过文件夹路径生成api
  • 配置http全局global.errs
代码语言:js
复制
const Router = require('koa-router');
const requireDirectory = require('require-directory');

class InitManager {
    static initCore(app) {
        InitManager.app = app
        InitManager.initLoadRouters();
        InitManager.loadHttpException();
        InitManager.loadConfig();
    }

    static loadConfig(path = '') {
        const configPath = path || process.cwd() + '/config/config.js'
        const config = require(configPath)
        global.config = config
    }

    static initLoadRouters() {
        const path = `${process.cwd()}/app/api/`
        const visitor = function (obj) {
            if (obj instanceof Router) {
                InitManager.app.use(obj.routes())
            }
        }

        requireDirectory(module, path, { visit: visitor })
    }

    static loadHttpException() {
        const errors = require('./http-exception')
        global.errs = errors
    }
}

module.exports = InitManager;

开始工作已完成

后续就是编写api了

未完待续,koa开发持续更新中...

感谢关注点赞评论~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • node这么多框架,怎么选
    • Express
    • Koa
    • NestJS
    • LoopBack
    • Hapi
  • 为什么选Koa
    • 开发微信小程序(记账小程序&h5通用api)
      • 需求规划:
      • 当时计划的TODOlist
      • 基于Koa二次开发
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档