Учебник Node по использованию TS на платформе Egg (1)

Node.js
Учебник Node по использованию TS на платформе Egg (1)

Node + Egg + TS + Mongodb + Resetful

  1. Как программист, прошедший путь от элегантных, объектно-ориентированных, профессиональных: C, C++, C#, JAVA, когда я начал писать JS, я отказался. Где этот пишущий код, явно пишущийconsole.log()Какие! ! !Мне слишком сложно не сказать мне даже несколько параметров и неправильный тип параметров.

  2. Мои предки:объектно-ориентированныйа также23 шаблона проектирования, потерял душу в этом коде JS.

  3. Кстати:asyncа такжеawaitДействительно ароматный.

  4. Онлайн-уроки представляют собой комбинацию небольшой части яйца, и на самом деле они не имеют силы нашей статьи. Без лишних слов, давайте начнем!

Как обычно, адрес местного туториала:GitHub.com/Два 010…

Операционная среда: Node, Yarn/NPM, MongoDB

egg — это фреймворк node.js, он довольно прост в использовании, его увидит каждый.

Узел + яйцо + ts + пример MongoDB

数据库保存
接口返回字段

Структура каталогов

项目结构

egg-demo
├── app
│   ├── controller (前端的请求会到这里来!)
│   │   └── home.ts
│   ├── model(数据库表结构抽象出来的模型)
│   │   └── User.ts
│   ├── service(controller 层不建议承载过多的业务,业务重时放在service层)
│   │   └── user.ts
│   └── router.ts (Url的相关映射)
├── config (框架的配置文件)
│   ├── config.default.ts
│   ├── config.local.ts
│   ├── config.prod.ts
│   └── plugin.ts
├── test (测试文件夹)
│   └── **/*.test.ts
├── typings (目录用于放置 d.ts 文件)
│   └── **/*.d.ts
├── README.md
├── package.json
├── tsconfig.json
└── tslint.json

настроить

Демо настраивается в двух местах:

  • база данных
  config.mongoose = {
    url: process.env.EGG_MONGODB_URL || 'mongodb://127.0.0.1/egg-demo',
    options: {},
  };
  • csrf (сначала закрыть, иначе сообщение сообщит об ошибке)
  config.security = {
    csrf: {
      enable: false,
    },
  };

router

Для интерфейсов в стиле сброса используйте ключевые слова http для обозначения действий и существительные для обозначения ресурсов. Например, пользователь: Для запросов «/user» спецификации в приведенном ниже коде сопоставляются с соответствующими функциями.

  router.get('/user', controller.home.getUser);
  router.post('/user', controller.home.addUser);
  router.put('/user', controller.home.updateUser);
  router.delete('/user', controller.home.deleteUser);

controller

Вот класс, который запрашивает соответствующую функцию.

  // 这里是get('/user')的处理函数
  public async getUser() {
    const ctx = this;
    
    // 这里就是随你怎么来。可以数据库查,或者别的。
    const user = { ... };
    // 返回的值
    ctx.body = user;
  }

  // 下面类似,不再解释了啊
  public async addUser() {
    const ctx = this;

    // 模拟前端传递过来的数据(方便测试)
    const user = new UserModel();
    user.userName = 'add user';
    user.userNo = 99;

    const res = await ctx.model.User.create(user);
    ctx.body = res;
  }

  public async deleteUser() {
    const ctx = this;

    const user = new UserModel();
    user.userNo = 99;

    const res = await UserModel.findOneAndRemove({ userNo: user.userNo });

    ctx.body = res;
  }

сервисный уровень

Здесь не о чем говорить, просто положите сюда какие-нибудь деловые штучки и пусть их вызывает контроллер или другие службы.

  /**
  * sayHi to you
  * @param name - your name
  */
  public async sayHi(name: string) {
    return `hi, ${name}`;
  }

Модель (нарисуйте ключевой момент, используйте внимание mongodb)

  1. Сначала мы создаем схему
/**
  * 定义一个User的Schema
*/
const UserSchema: Schema = new Schema({
  userNo: {
    type: Number,
    index: true,
  },

  userName: String,
},
  {
    timestamps: true,
  },
);
  1. показатель
// userNo 为索引
UserSchema.index({ userNo: 1, });
  1. Методы экземпляра и статические методы
// UserSchema的实例方法
UserSchema.methods.userInstanceTestMethods = function () {

  const user: IUser = new UserModel();
  user.userName = '我是实例化方法测试';
  user.userNo = 9527;

  return user;
};

// UserSchema的实例方法
UserSchema.statics.userStaticTestMethods = function () {

  const user: IUser = new UserModel();
  user.userName = '我是静态方法测试';
  user.userNo = 9528;

  return user;
};
  1. Создать поле пользовательского интерфейса
/**
  * 用户字段接口
*/
export interface IUser {

  userNo: number;

  userName: string;
}
  1. Определение метода экземпляра и интерфейса статического метода, примечание: здесь интерфейс должен соответствовать имени и возвращаемому значению функции, определенной в схеме.
export interface IUserDocument extends IUser, Document {
  /**
  * 实例方法接口(名称需要和Schema的方法名一样)
  */
 userInstanceTestMethods: () => IUser;
}
/**
  * 静态方法接口
*/
export interface IUserModel extends Model<IUserDocument> {

  /**
   * 静态方法
   */
  userStaticTestMethods: () => IUser;
}
  1. Просто экспортируйте модель.
export const UserModel = model<IUserDocument, IUserModel>('User', UserSchema);
  1. Для того, чтобы бояться использовать ctx.model.User, нам нужно смонтировать UserSchema в ctx
// egg-mongoose注入
export default (app: Application) => {

  const mongoose = app.mongoose;
  // 这里为了挂载到ctx中,让正常ctx.model.User也能使用
  mongoose.model<IUserDocument, IUserModel>('User', UserSchema);
};

Использовать модель

Используя режим, можно использовать интерфейс поля IUser, метод экземпляра, статический метод.

  // 这里的user是: IUser的类型。然后就能尽情的点点点啦!
  const user = await UserModel.findOne();
  // 等价于
  const users = await this.ctx.model.User.find();
  // 实例方法
  const newUser = new UserModel();
  newUser.userInstanceTestMethods();
  // 静态方法
  UserModel.userStaticTestMethods();

Наконец-то модульные тесты! ! !

Многим может показаться, что написание модульных тестов без их написания — пустая трата времени. Но когда вы обнаружите, что вам нужно рефакторить и не хватает юнит-тестов, вы подумаете, какого черта, не смей двигаться! ! ! Поэтому я считаю, что писать юнит-тесты все-таки нужно, это дело занимает некоторое время, но на поздней стадии это хорошо.

 test/app/controller/home.test.ts
    √ should GET / (49ms)
    √ addUser (39ms)
    √ getUser
    √ getUsers
    √ updateUser
    √ deleteUser
    √ testStaticMethods
    √ testInstanceFunction

  test/app/service/Test.test.js
    √ sayHi
    √ testUserInstanceServiceMethods
    √ testUserInstanceServiceMethods

  11 passing (4s)

Я очень рад, что он попал в зеленый √ √.

Сегодня немного поздновато, позже напишу: запланированные задачи, GraphQL, redis, деплоймент и т.д.