手记

【金秋打卡】第8天 Egg.js 结合 Mongoose

课程名称:web前端架构师

课程章节:第14周 第八章 添加 Mongoose 以及 egg.js 插件原理

主讲老师:张轩

课程内容: Egg.js 结合 Mongoose

Egg.js 结合 Mongoose

添加 mongoose到 egg.js

在 app.js 中将 mongoose 挂载到 app 上

import { IBoot, Application } from 'egg';
import { createConnection } from 'mongoose';

export default class AppBook implements IBoot {
  private readonly app: Application;
  constructor(app: Application) {
    this.app = app;
    const { url } = this.app.config.mongoose;
    const db = createConnection(url);
    db.on('connected', () => {
      console.log('connected success');
    });
    this.app.mongoose = db;
  }
  // 配置文件即将加载,这是最后动态修改配置的时机
  configWillLoad(): void {
    this.app.config.coreMiddleware.push('myLogger');
  }
  async willReady(): Promise<void> {
    console.log(this.app.config.coreMiddleware);
  }
}

在这之前,我们需要将 MongoDB 信息放到 配置文件中

import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';

export default (appInfo: EggAppInfo) => {
  const config = {} as PowerPartial<EggAppConfig>;
  // add your special config in here
  const bizConfig = {
    sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`,
    myLogger: {
      allowedMethod: [ 'POST' ],
    },
    // 将 mongoose 放到这里,是因为这里 在app.ts 书写时就会有提示信息
    mongoose: 'mongodb://user:pass@localhost:27017/dbName',
  };

  // the return config will combines to EggAppConfig
  return {
    ...config as {},
    ...bizConfig,
  };
};

这样就将 mongoose 挂载到 app 上了,这是还需要声明下 app.mongoose 到类型,可以在 typings/index.d.ts 上声明

import 'egg';
import { type Connection } from  'mongoose'

declare module 'egg' {
  interface Application {
    mongoose: Connection
  }
}

添加 Servie, 这里我们创建一个 User Service

首先创建 User Schema

import { Service } from 'egg';
import { Schema } from 'mongoose';
const ObjectId = Schema.Types.ObjectId;
const UserSchema = new Schema({
  username: String,
  password: {
    type: String,
    select: false,
  },
  hobbies: [ String ],
  date: Date,
  createAt: Date,
  age: Number,
  team: {
    type: ObjectId,
    ref: 'team',
  },
}, {
  collection: 'users',
});

创建model,然后我们创建一个 getUser 方法,用来查询用户

export default class UserController extends Service {
  public async getUser() {
    const User = this.getUserModel();
    console.log(await User.find());
    return User.find().limit(10);
  }
  private getUserModel() {
    return this.app.mongoose.model('User', UserSchema);
  }
}

这样我们就可以在 controller 中使用这个service,来查询用户信息了

import { Controller } from 'egg';
export default class UserController extends Controller {
  public async index() {
    const { ctx } = this;
    ctx.body = await ctx.service.user.getUser();
    ctx.logger.debug('debug info');
  }
}

这样就可以通过访问对应接口,来查询用户了

但是上面代码中,我们是将 Mongoose Model 写在了service 下,我们可以将 Model 写在一个 model 文件夹下,任何目录下可以通过访问 app.model.xxx来操作 MongoDB 的话,就会更加方便

});
export default class UserController extends Service {
  public async getUser() {
    return  this.app.model.User.find().limit(10)
  }
}

实现这个功能之前需要先了解下 egg.js 的加载器

加载器 Loader

Egg 在 Koa 的基础上进行增强最重要的就是基于一定的约定,根据功能差异将代码放到不同的目录下管理,对整体团队的开发成本提升有着明显的效果。Loader 实现了这套约定,并抽象了很多底层 API 可以进一步扩展。

文件顺序

上面已经列出了默认会加载的文件,Egg 会按如下文件顺序加载,每个文件或目录再根据 loadUnit 的顺序去加载(应用、框架、插件各有不同)。

  • 加载 plugin,找到应用和框架,加载 config/plugin.js
  • 加载 config,遍历 loadUnit 加载 config/config.{env}.js
  • 加载 extend,遍历 loadUnit 加载 app/extend/xx.js
  • 自定义初始化,遍历 loadUnit 加载 app.js 和 agent.js
  • 加载 service,遍历 loadUnit 加载 app/service 目录
  • 加载 middleware,遍历 loadUnit 加载 app/middleware 目录
  • 加载 controller,加载应用的 app/controller 目录
  • 加载 router,加载应用的 app/router.js

生命周期

框架提供了这些生命周期函数供开发人员处理:

  • 配置文件即将加载,这是最后动态修改配置的时机(configWillLoad)
  • 配置文件加载完成(configDidLoad)
  • 文件加载完成(didLoad)
  • 插件启动完毕(willReady)
  • worker 准备就绪(didReady)
  • 应用启动完成(serverDidReady)
  • 应用即将关闭(beforeClose)

我们可以将我们加载 model 文件放在 willReady 中

加载器函数 loadToApp

用于加载一个目录下的文件到 app,比如 app/controller/home.js 会加载到 app.controller.home。

// app.js
// 以下只是示例,加载 controller 请用 loadController
module.exports = (app) => {
  const directory = path.join(app.config.baseDir, 'app/controller');
  app.loader.loadToApp(directory, 'controller');
};

一共有三个参数 loadToApp(directory, property, LoaderOptions)

我们可以使用 loalToApp 方法来加载 model

// app.ts
import { IBoot, Application } from 'egg';
import path from 'path';
...
export default class AppBook implements IBoot {
  private readonly app: Application;
  ...
  // 配置文件即将加载,这是最后动态修改配置的时机
  configWillLoad(): void {
    const dir = path.join(this.app.config.baseDir, 'app/model');
    this.app.loader.loadToApp(dir, 'model', {
      caseStyle: 'Upper',
    });
  }
}

0人推荐
随时随地看视频
慕课网APP