Node + Egg + TS + typegoose + Resetful + schedule + type-graphql+ websocket

psc.jpg
在使用了之前教程的骨架代碼一段時候,有同學說,typegoose出新包,大改了?,F(xiàn)在寫法變化了很多。于是就有了這個 typegoose新包的骨架代碼教程。
本次教材地址:https://github.com/liangwei0101/egg-demo.git
版本:
- node:v12.14.0
- @typegoose/typegoose: 6.4.0
先對比下前后typegoose之前的寫法
- 引入的包不一樣了
// 之前是這樣寫的
import { index, prop, instanceMethod, staticMethod } from 'typegoose';
// 現(xiàn)在是這樣寫的
import { index, getModelForClass, prop } from '@typegoose/typegoose';
- 實例方法和之前不一樣了(簡潔了許多)
// 之前實例方法是加注解就好了
export default class User extends Typegoose {
@instanceMethod
public async userInstanceTestMethods(this: InstanceType<User>) {
}
}
// 現(xiàn)在直接寫就好了不用注解
export default class User extends Typegoose {
public async userInstanceTestMethods() {
}
}
- 靜態(tài)方法和之前不一樣了(簡潔了許多)
// 之前靜態(tài)方法是加注解就好了
export default class User extends Typegoose {
@staticMethod
public async userStaticTestMethods(this: InstanceType<User>) {
}
}
// 現(xiàn)在直接寫就好了不用注解
export default class User extends Typegoose {
public static async userStaticTestMethods() {
}
}
- 導出Model, 現(xiàn)在getModelForClass直接使用即可
// 之前是這樣寫的
export const UserModel = new User().getModelForClass(User);
// 現(xiàn)在是這樣寫的
export const UserModel = getModelForClass(User);
- buildSchema 函數(shù) (單元測試的ctx.model可能會需要)
// 從class 獲取 Schema
const TradeSchema = buildSchema(User);
// 如果需要Schema的話
export default (app: Application) => {
const mongoose = app.mongoose;
const UserSchema = buildSchema(Order);
UserSchema.loadClass(OrderClass);
return mongoose.model('Order', UserSchema);
}
type-graphql 使用JSON類型
找了很久type-graphql使用any或者json的文檔或者例子,都是只支持type-graphql的基礎(chǔ)類型,和class類型。然后,就自己定義一個JSON類型吧。
- GraphQLScalarType 自定義(我封裝了兩個,一個查詢用的,一個新增用的)
import { GraphQLScalarType } from "graphql";
// 自定義 名稱為JSON的類型
export const JosnScalar = new GraphQLScalarType({
name: "JSON",
description: "驗證 JSON 類型",
parseValue(value: any) {
if (Object.prototype.toString.call(value) !== '[object Object]') {
throw new Error('親,參數(shù)不是一個對象呢!');
}
return value;
},
serialize(value: any) {
return value;
},
});
- 使用自定義JSON類型例子一
// 輸入?yún)?shù)
@ArgsType()
export class DefaultMutation {
@Field(() => JosnScalar, { nullable: true })
data: any;
}
@Mutation(() => User, { description: '增加用戶' })
async addUser(@Args() { data }: DefaultMutation, @Ctx() ctx: Context) {
// 這里的 data 指向 DefaultMutation 屬性的data也就是any類型
const user = await ctx.service.user.createUser(data);
return user;
}
- 使用自定義JSON類型例子二
@ArgsType()
export class DefaultQuery {
@Field(() => JosnScalar, { nullable: true })
filter: any;
@Field(() => JosnScalar, { nullable: true })
order: any;
@Field(() => JosnScalar, { nullable: true })
page: any;
}
// 使用
@Query(() => [User], { description: '查詢用戶列表' })
async getUser(@Args() { filter, order, page }: DefaultQuery, @Ctx() ctx: Context) {
return await ctx.service.user.filterUser(filter, order, page);
}
egg中 mongoose 的 transaction
- 提取公用函數(shù),封裝到上下文ctx中
// extend/context.ts
import { Context } from 'egg';
export default {
// 獲取session,回滾事務
async getSession(this: Context) {
// Start a session.
const session = await this.app.mongoose.startSession();
// Start a transaction
// 這里因為獲取到的session也是要startTransaction,所以,就一并在這寫掉
session.startTransaction();
return session
}
}
- 事務使用
mongodb的事務比較low,開啟事務,需要副本集,否則會報: Transaction numbers are only allowed on a replica set member or mongos
/**
* 測試事務
*/
public async testErrorTransaction() {
const session: any = await this.ctx.getSession();
try {
const user = new UserModel();
user.userName = 'add user';
user.userNo = 103;
(await UserModel.create(user)).$session(session)
// 沒有userNo將會報錯
const user1 = new UserModel();
(await UserModel.create(user)).$session(session)
console.log(user1);
// 提交事務
await session.commitTransaction();
} catch (err) {
// 事務回滾
await session.abortTransaction();
throw err;
} finally {
await session.endSession();
}
}
這個骨架使用應該沒有啥問題啦,有啥問題歡迎大家指出。謝謝!別忘記給我點星星哦,再次謝謝啦!