baserepositry
parent
7d6b4aaf79
commit
c9ba07db76
|
@ -1,22 +1,25 @@
|
||||||
import { Repository } from 'typeorm';
|
import { BaseRepository } from '@/modules/database/base/repository';
|
||||||
|
|
||||||
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
|
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
|
||||||
|
|
||||||
import { CommentEntity } from '../entities';
|
import { CommentEntity } from '../entities';
|
||||||
import { PostEntity } from '../entities/post.entity';
|
import { PostEntity } from '../entities/post.entity';
|
||||||
|
|
||||||
@CustomRepository(PostEntity)
|
@CustomRepository(PostEntity)
|
||||||
export class PostRepository extends Repository<PostEntity> {
|
export class PostRepository extends BaseRepository<PostEntity> {
|
||||||
buildBaseQB() {
|
protected _qbName = 'post';
|
||||||
return this.createQueryBuilder('post')
|
|
||||||
.leftJoinAndSelect('post.category', 'category')
|
protected orderBy = 'createdAt';
|
||||||
.leftJoinAndSelect('post.tags', 'tags')
|
|
||||||
|
postBuildBaseQB() {
|
||||||
|
return this.buildBaseQB()
|
||||||
|
.leftJoinAndSelect(`${this.qbName}.category`, 'category')
|
||||||
|
.leftJoinAndSelect(`${this.qbName}.tags`, 'tags')
|
||||||
.addSelect((subQuery) => {
|
.addSelect((subQuery) => {
|
||||||
return subQuery
|
return subQuery
|
||||||
.select('COUNT(c.id)', 'count')
|
.select('COUNT(c.id)', 'count')
|
||||||
.from(CommentEntity, 'c')
|
.from(CommentEntity, 'c')
|
||||||
.where('c.post.id = post.id');
|
.where(`c.post.id = ${this.qbName}.tags`);
|
||||||
}, 'commentCount')
|
}, 'commentCount')
|
||||||
.loadRelationCountAndMap('post.commentCount', 'post.comments');
|
.loadRelationCountAndMap(`${this.qbName}.commentCount`, `${this.qbName}.commentCount`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
import { Repository } from 'typeorm';
|
import { BaseRepository } from '@/modules/database/base/repository';
|
||||||
|
|
||||||
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
|
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
|
||||||
|
|
||||||
import { TagEntity, PostEntity } from '../entities';
|
import { TagEntity, PostEntity } from '../entities';
|
||||||
|
|
||||||
@CustomRepository(TagEntity)
|
@CustomRepository(TagEntity)
|
||||||
export class TagRepository extends Repository<TagEntity> {
|
export class TagRepository extends BaseRepository<TagEntity> {
|
||||||
buildBaseQB() {
|
protected _qbName = 'tag';
|
||||||
return this.createQueryBuilder('tag')
|
|
||||||
.leftJoinAndSelect('tag.posts', 'posts')
|
protected orderBy = 'name';
|
||||||
|
|
||||||
|
tagbuildBaseQB() {
|
||||||
|
return this.buildBaseQB()
|
||||||
|
.leftJoinAndSelect(`${this.qbName}.posts`, 'posts')
|
||||||
.addSelect(
|
.addSelect(
|
||||||
(subQuery) => subQuery.select('COUNT(p.id)', 'count').from(PostEntity, 'p'),
|
(subQuery) => subQuery.select('COUNT(p.id)', 'count').from(PostEntity, 'p'),
|
||||||
'postCount',
|
'postCount',
|
||||||
)
|
)
|
||||||
.orderBy('postCount', 'DESC')
|
.orderBy('postCount', 'DESC')
|
||||||
.loadRelationCountAndMap('tag.postCount', 'tag.posts');
|
.loadRelationCountAndMap(`${this.qbName}.postCount`, `${this.qbName}.posts`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ObjectLiteral, Repository, SelectQueryBuilder } from 'typeorm';
|
||||||
|
|
||||||
|
import { getOrderBy } from '../helpers';
|
||||||
|
import { OrderQueryType } from '../types';
|
||||||
|
|
||||||
|
export abstract class BaseRepository<E extends ObjectLiteral> extends Repository<E> {
|
||||||
|
protected abstract _qbName: string;
|
||||||
|
|
||||||
|
protected abstract orderBy?: OrderQueryType;
|
||||||
|
|
||||||
|
get qbName(): string {
|
||||||
|
return this._qbName;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildBaseQB() {
|
||||||
|
return this.createQueryBuilder(this.qbName);
|
||||||
|
}
|
||||||
|
|
||||||
|
addOrderBy(qb: SelectQueryBuilder<E>, orderby?: OrderQueryType) {
|
||||||
|
const orderBy = orderby ?? this.orderBy;
|
||||||
|
return getOrderBy(qb, this.qbName, orderBy);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
import { ForbiddenException, NotFoundException } from '@nestjs/common';
|
||||||
|
import { isNil } from 'lodash';
|
||||||
|
import { In, ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
||||||
|
|
||||||
|
import { SelectTrashMode } from '@/modules/content/constants';
|
||||||
|
|
||||||
|
import { TreeChildrenResolve } from '../constants';
|
||||||
|
import { paginate, treePaginate } from '../helpers';
|
||||||
|
import { PaginateOptions, PaginateReturn, QueryHook, ServiceListQueryOption } from '../types';
|
||||||
|
|
||||||
|
import { BaseRepository } from './repository';
|
||||||
|
import { BaseTreeRepository } from './tree.repository';
|
||||||
|
|
||||||
|
export abstract class BaseService<
|
||||||
|
E extends ObjectLiteral,
|
||||||
|
R extends BaseRepository<E> | BaseTreeRepository<E>,
|
||||||
|
P extends ServiceListQueryOption<E> = ServiceListQueryOption<E>,
|
||||||
|
> {
|
||||||
|
protected repository: R;
|
||||||
|
|
||||||
|
protected enableTrash = false;
|
||||||
|
|
||||||
|
constructor(repository: R) {
|
||||||
|
this.repository = repository;
|
||||||
|
if (
|
||||||
|
!(this.repository instanceof BaseTreeRepository) &&
|
||||||
|
!(this.repository instanceof BaseRepository)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
'Repository must instance of BaseRepository or BaseTreeRepository in DataService!',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async buildItemQB(id: string, qb: SelectQueryBuilder<E>, callback?: QueryHook<E>) {
|
||||||
|
qb.where(`${this.repository.qbName}.id = :id`, { id });
|
||||||
|
if (callback) return callback(qb);
|
||||||
|
// 短路运算符,不会阻塞后续代码执行 如果callback执行
|
||||||
|
// callback && callback(qb);
|
||||||
|
return qb;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async buildListQB(qb: SelectQueryBuilder<E>, options: P, callback?: QueryHook<E>) {
|
||||||
|
const { trashed } = options ?? {};
|
||||||
|
if (
|
||||||
|
this.enableTrash &&
|
||||||
|
(trashed === SelectTrashMode.ALL || trashed === SelectTrashMode.ONLY)
|
||||||
|
) {
|
||||||
|
qb.withDeleted();
|
||||||
|
if (trashed === SelectTrashMode.ONLY) {
|
||||||
|
qb.where(`${this.repository.qbName}.deletedAt IS NOT NULL`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callback ? callback(qb) : qb;
|
||||||
|
}
|
||||||
|
|
||||||
|
async list(options?: P, callback?: QueryHook<E>): Promise<E[]> {
|
||||||
|
if (this.repository instanceof BaseRepository) {
|
||||||
|
const qb = await this.buildListQB(this.repository.buildBaseQB(), options, callback);
|
||||||
|
return qb.getMany();
|
||||||
|
}
|
||||||
|
const { trashed = SelectTrashMode.NONE } = options ?? {};
|
||||||
|
const tree = await this.repository.findTrees({
|
||||||
|
...options,
|
||||||
|
withTrashed:
|
||||||
|
this.enableTrash &&
|
||||||
|
(trashed === SelectTrashMode.ALL || trashed === SelectTrashMode.ONLY),
|
||||||
|
onlyTrashed: this.enableTrash && trashed === SelectTrashMode.ONLY,
|
||||||
|
});
|
||||||
|
return this.repository.toFlatTrees(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
async basePaginate(
|
||||||
|
options?: PaginateOptions & P,
|
||||||
|
callback?: QueryHook<E>,
|
||||||
|
): Promise<PaginateReturn<E>> {
|
||||||
|
const queryOptions = options ?? {};
|
||||||
|
if (this.repository instanceof BaseRepository) {
|
||||||
|
const qb = await this.buildListQB(this.repository.buildBaseQB(), options, callback);
|
||||||
|
return paginate(qb, queryOptions);
|
||||||
|
}
|
||||||
|
const data = await this.list(options, callback);
|
||||||
|
return treePaginate(queryOptions, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async detail(id: string, callback?: QueryHook<E>): Promise<E> {
|
||||||
|
const qb = await this.buildItemQB(id, this.repository.buildBaseQB(), callback);
|
||||||
|
|
||||||
|
const item = qb.getOne();
|
||||||
|
if (!item) {
|
||||||
|
throw new NotFoundException(`${this.repository.qbName} ${id} not exists!`);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首先判断是否是树形结构,如果是树形结构,那么就会调用findDescendantsTree方法,否则直接调用find方法
|
||||||
|
async delete(ids: string[], trash?: boolean) {
|
||||||
|
let items: E[] = [];
|
||||||
|
if (this.repository instanceof BaseTreeRepository) {
|
||||||
|
items = await this.repository.find({
|
||||||
|
where: { id: In(ids) as any },
|
||||||
|
withDeleted: this.enableTrash ? true : undefined,
|
||||||
|
relations: ['parent', 'children'],
|
||||||
|
});
|
||||||
|
if (this.repository.childrenResolve === TreeChildrenResolve.UP) {
|
||||||
|
for (const item of items) {
|
||||||
|
if (isNil(item.children) || item.children.length <= 0) continue;
|
||||||
|
const nchildren = [...item.children].map((c) => {
|
||||||
|
c.parent = item.parent;
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
await this.repository.save(nchildren);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
items = await this.repository.find({
|
||||||
|
where: { id: In(ids) as any },
|
||||||
|
withDeleted: this.enableTrash ? true : undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.enableTrash && trash) {
|
||||||
|
const directs = items.filter((item) => !isNil(item.deletedAt));
|
||||||
|
const softs = items.filter((item) => isNil(item.deletedAt));
|
||||||
|
return [
|
||||||
|
...(await this.repository.remove(directs)),
|
||||||
|
...(await this.repository.softRemove(softs)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return this.repository.remove(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
async restore(ids: string[]) {
|
||||||
|
const qb = this.repository.buildBaseQB();
|
||||||
|
if (!this.enableTrash) {
|
||||||
|
throw new ForbiddenException(
|
||||||
|
`Can't to restore ${this.repository.qbName} because Trash is not enabled!`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const items = await qb.withDeleted().whereInIds(ids).getMany();
|
||||||
|
const trashedIds = items.map((item) => item.id);
|
||||||
|
if (trashedIds.length > 0) {
|
||||||
|
this.repository.restore(trashedIds);
|
||||||
|
return qb.whereInIds(trashedIds).getMany();
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
create(data: any, ...others: any[]): Promise<E> {
|
||||||
|
throw new ForbiddenException(`Can not to create ${this.repository.qbName}!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(data: any, ...others: any[]): Promise<E> {
|
||||||
|
throw new ForbiddenException(`Can not to update ${this.repository.qbName}!`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
import { pick, unset } from 'lodash';
|
||||||
|
import {
|
||||||
|
EntityManager,
|
||||||
|
EntityTarget,
|
||||||
|
FindOptionsUtils,
|
||||||
|
FindTreeOptions,
|
||||||
|
ObjectLiteral,
|
||||||
|
QueryRunner,
|
||||||
|
SelectQueryBuilder,
|
||||||
|
TreeRepository,
|
||||||
|
TreeRepositoryUtils,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
import { TreeChildrenResolve } from '../constants';
|
||||||
|
import { getOrderBy } from '../helpers';
|
||||||
|
import { OrderQueryType, QueryParams } from '../types';
|
||||||
|
|
||||||
|
export abstract class BaseTreeRepository<E extends ObjectLiteral> extends TreeRepository<E> {
|
||||||
|
protected _qbName = 'treeEntity';
|
||||||
|
|
||||||
|
protected _childrenResolve?: TreeChildrenResolve;
|
||||||
|
|
||||||
|
protected orderBy?: OrderQueryType;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
constructor(target: EntityTarget<E>, manager: EntityManager, queryRunner?: QueryRunner) {
|
||||||
|
super(target, manager, queryRunner);
|
||||||
|
}
|
||||||
|
|
||||||
|
get qbName(): string {
|
||||||
|
return this._qbName;
|
||||||
|
}
|
||||||
|
|
||||||
|
get childrenResolve() {
|
||||||
|
return this._childrenResolve;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildBaseQB(qb?: SelectQueryBuilder<E>): SelectQueryBuilder<E> {
|
||||||
|
const queryBuilder = qb || this.createQueryBuilder(this.qbName);
|
||||||
|
return queryBuilder.leftJoinAndSelect(`${this.qbName}.parent`, 'parent');
|
||||||
|
}
|
||||||
|
|
||||||
|
addOrderByQuery(qb: SelectQueryBuilder<E>, orderBy: OrderQueryType): SelectQueryBuilder<E> {
|
||||||
|
const ob = orderBy ?? this.orderBy;
|
||||||
|
return getOrderBy(qb, this.qbName, ob);
|
||||||
|
}
|
||||||
|
|
||||||
|
async findDescendantsTree(entity: E, options?: FindTreeOptions & QueryParams<E>) {
|
||||||
|
const { addQuery, onlyTrashed, orderBy, withTrashed } = options ?? {};
|
||||||
|
const qb = this.buildBaseQB(
|
||||||
|
this.createDescendantsQueryBuilder(this.qbName, 'treeClosure', entity),
|
||||||
|
);
|
||||||
|
addQuery
|
||||||
|
? await addQuery(this.addOrderByQuery(qb, orderBy))
|
||||||
|
: this.addOrderByQuery(qb, orderBy);
|
||||||
|
withTrashed
|
||||||
|
? qb.withDeleted()
|
||||||
|
: onlyTrashed && qb.where(`${this.qbName}.deletedAt IS NOT NULL`);
|
||||||
|
FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, pick(options, ['relations', 'depth']));
|
||||||
|
const entites = await qb.getRawAndEntities();
|
||||||
|
const relationMaps = TreeRepositoryUtils.createRelationMaps(
|
||||||
|
this.manager,
|
||||||
|
this.metadata,
|
||||||
|
this.qbName,
|
||||||
|
entites.raw,
|
||||||
|
);
|
||||||
|
TreeRepositoryUtils.buildChildrenEntityTree(
|
||||||
|
this.metadata,
|
||||||
|
entity,
|
||||||
|
entites.entities,
|
||||||
|
relationMaps,
|
||||||
|
{
|
||||||
|
depth: -1,
|
||||||
|
...pick(options, ['relations']),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
async findTrees(options?: FindTreeOptions & QueryParams<E>) {
|
||||||
|
const roots = await this.findRoots(options);
|
||||||
|
// foreach 不会等待异步操作,所以这里使用 Promise.all 来等待所有异步操作完成
|
||||||
|
// roots.forEach(async (root) => this.findDescendantsTree(root, options));
|
||||||
|
Promise.all(roots.map((root) => this.findDescendantsTree(root, options)));
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
|
||||||
|
async toFlatTrees(trees: E[], depth = 0, parent: E | null = null): Promise<E[]> {
|
||||||
|
const data: Omit<E, 'children'>[] = [];
|
||||||
|
for (const item of trees) {
|
||||||
|
(item as any).depth = depth;
|
||||||
|
(item as any).parent = parent;
|
||||||
|
const { children } = item;
|
||||||
|
unset(item, 'children');
|
||||||
|
data.push(item);
|
||||||
|
data.push(...(await this.toFlatTrees(children, depth + 1, item)));
|
||||||
|
}
|
||||||
|
return data as E[];
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,16 @@
|
||||||
export const CUSTOM_REPOSITORY_METADATA = 'CUSTOM_REPOSITORY_METADATA';
|
export const CUSTOM_REPOSITORY_METADATA = 'CUSTOM_REPOSITORY_METADATA';
|
||||||
|
/**
|
||||||
|
* 排序方式
|
||||||
|
*/
|
||||||
|
export enum OrderType {
|
||||||
|
ASC = 'ASC',
|
||||||
|
DESC = 'DESC',
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 树形模型在删除父级后子级的处理方式
|
||||||
|
*/
|
||||||
|
export enum TreeChildrenResolve {
|
||||||
|
DELETE = 'delete',
|
||||||
|
UP = 'up',
|
||||||
|
ROOT = 'root',
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
||||||
|
|
||||||
import { PaginateOptions, PaginateReturn } from './types';
|
import { OrderQueryType, PaginateOptions, PaginateReturn } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页函数
|
* 分页函数
|
||||||
|
@ -62,3 +62,29 @@ export function treePaginate<E extends ObjectLiteral>(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getOrderBy<E extends ObjectLiteral>(
|
||||||
|
qb: SelectQueryBuilder<E>,
|
||||||
|
alians: string,
|
||||||
|
order?: OrderQueryType,
|
||||||
|
) {
|
||||||
|
if (!order) {
|
||||||
|
return qb;
|
||||||
|
}
|
||||||
|
if (typeof order === 'string') {
|
||||||
|
return qb.orderBy(`${alians}.${order}`, 'DESC');
|
||||||
|
}
|
||||||
|
if (Array.isArray(order)) {
|
||||||
|
for (const item of order) {
|
||||||
|
if (typeof item === 'string') {
|
||||||
|
return qb.orderBy(`${alians}.${item}`, 'DESC');
|
||||||
|
}
|
||||||
|
if (item.name && item.order) {
|
||||||
|
return qb.orderBy(`${alians}.${item.name}`, item.order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return qb.orderBy(`${alians}.${order.name}`, order.order);
|
||||||
|
}
|
||||||
|
return qb;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
import { FindTreeOptions, ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
||||||
|
|
||||||
|
import { SelectTrashMode } from '../content/constants';
|
||||||
|
|
||||||
|
import { OrderType } from './constants';
|
||||||
|
|
||||||
export type QueryHook<E> = (qb: SelectQueryBuilder<E>) => Promise<SelectQueryBuilder<E>>;
|
export type QueryHook<E> = (qb: SelectQueryBuilder<E>) => Promise<SelectQueryBuilder<E>>;
|
||||||
/**
|
/**
|
||||||
|
@ -48,3 +52,46 @@ export interface PaginateReturn<E extends ObjectLiteral> {
|
||||||
meta: PaginateMeta;
|
meta: PaginateMeta;
|
||||||
items: E[];
|
items: E[];
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 排序类型,{字段名称: 排序方法}
|
||||||
|
* 如果多个值则传入数组即可
|
||||||
|
* 排序方法不设置,默认DESC
|
||||||
|
*/
|
||||||
|
export type OrderQueryType =
|
||||||
|
| string
|
||||||
|
| { name: string; order: `${OrderType}` }
|
||||||
|
| Array<{ name: string; order: `${OrderType}` } | string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据列表查询类型
|
||||||
|
*/
|
||||||
|
export interface QueryParams<E extends ObjectLiteral> {
|
||||||
|
addQuery?: QueryHook<E>;
|
||||||
|
orderBy?: OrderQueryType;
|
||||||
|
withTrashed?: boolean;
|
||||||
|
onlyTrashed?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 服务类数据列表查询类型
|
||||||
|
*/
|
||||||
|
export type ServiceListQueryOption<E extends ObjectLiteral> =
|
||||||
|
| ServiceListQueryOptionWithTrashed<E>
|
||||||
|
| ServiceListQueryOptionNotWithTrashed<E>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带有软删除的服务类数据列表查询类型
|
||||||
|
*/
|
||||||
|
type ServiceListQueryOptionWithTrashed<E extends ObjectLiteral> = Omit<
|
||||||
|
FindTreeOptions & QueryParams<E>,
|
||||||
|
'withTrashed'
|
||||||
|
> & {
|
||||||
|
trashed?: `${SelectTrashMode}`;
|
||||||
|
} & Record<string, any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不带软删除的服务类数据列表查询类型
|
||||||
|
*/
|
||||||
|
type ServiceListQueryOptionNotWithTrashed<E extends ObjectLiteral> = Omit<
|
||||||
|
ServiceListQueryOptionWithTrashed<E>,
|
||||||
|
'trashed'
|
||||||
|
>;
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
async function test1(obj: any) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(
|
||||||
|
(o) => {
|
||||||
|
o.name = '1111';
|
||||||
|
return resolve(o);
|
||||||
|
},
|
||||||
|
1000,
|
||||||
|
obj,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const aa = { name: '2222' };
|
||||||
|
|
||||||
|
test1(aa).then((res) => {
|
||||||
|
console.log(res, '2');
|
||||||
|
});
|
Loading…
Reference in New Issue