Saltar al contenido principal

Listeners y Subscriptores de Entidades

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

¿Qué es un Listener de Entidad?

Cualquiera de tus entidades puede tener métodos con lógica personalizada que escuchan eventos específicos de la entidad. Debes marcar estos métodos con decoradores especiales según el evento que quieras escuchar.

Nota: Evita realizar llamadas a la base de datos dentro de un listener. En su lugar, utiliza subscriptores.

@AfterLoad

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @AfterLoad. TypeORM lo llamará cada vez que la entidad se cargue usando QueryBuilder o métodos de búsqueda del repositorio/manager. Ejemplo:

@Entity()
export class Post {
@AfterLoad()
updateCounters() {
if (this.likesCount === undefined) this.likesCount = 0
}
}

@BeforeInsert

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @BeforeInsert. TypeORM lo llamará antes de insertar la entidad usando save del repositorio/manager. Ejemplo:

@Entity()
export class Post {
@BeforeInsert()
updateDates() {
this.createdDate = new Date()
}
}

@AfterInsert

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @AfterInsert. TypeORM lo llamará después de insertar la entidad usando save del repositorio/manager. Ejemplo:

@Entity()
export class Post {
@AfterInsert()
resetCounters() {
this.counters = 0
}
}

@BeforeUpdate

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @BeforeUpdate. TypeORM lo llamará antes de actualizar una entidad existente usando save del repositorio/manager. Ten en cuenta que esto ocurrirá solo cuando se modifique información en el modelo. Si ejecutas save sin modificar nada en el modelo, @BeforeUpdate y @AfterUpdate no se ejecutarán. Ejemplo:

@Entity()
export class Post {
@BeforeUpdate()
updateDates() {
this.updatedDate = new Date()
}
}

@AfterUpdate

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @AfterUpdate. TypeORM lo llamará después de actualizar una entidad existente usando save del repositorio/manager. Ejemplo:

@Entity()
export class Post {
@AfterUpdate()
updateCounters() {
this.counter = 0
}
}

@BeforeRemove

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @BeforeRemove y TypeORM lo llamará antes de que una entidad sea eliminada usando el remove del repositorio o manager. Ejemplo:

@Entity()
export class Post {
@BeforeRemove()
updateStatus() {
this.status = "removed"
}
}

@AfterRemove

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @AfterRemove. TypeORM lo llamará después de eliminar la entidad usando remove del repositorio/manager. Ejemplo:

@Entity()
export class Post {
@AfterRemove()
updateStatus() {
this.status = "removed"
}
}

@BeforeSoftRemove

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @BeforeSoftRemove y TypeORM lo llamará antes de que una entidad sea eliminada de forma suave (soft removed) usando el softRemove del repositorio o manager. Ejemplo:

@Entity()
export class Post {
@BeforeSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}

@AfterSoftRemove

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @AfterSoftRemove. TypeORM lo llamará después de eliminar suavemente la entidad usando softRemove del repositorio/manager. Ejemplo:

@Entity()
export class Post {
@AfterSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}

@BeforeRecover

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @BeforeRecover y TypeORM lo llamará antes de que una entidad sea recuperada usando el recover del repositorio o manager. Ejemplo:

@Entity()
export class Post {
@BeforeRecover()
updateStatus() {
this.status = "recovered"
}
}

@AfterRecover

Puedes definir un método con cualquier nombre en la entidad y marcarlo con @AfterRecover. TypeORM lo llamará después de recuperar la entidad usando recover del repositorio/manager. Ejemplo:

@Entity()
export class Post {
@AfterRecover()
updateStatus() {
this.status = "recovered"
}
}

¿Qué es un Subscriptor?

Marca una clase como suscriptor de eventos que puede escuchar eventos específicos de entidades o cualquier evento de entidad. Los eventos se disparan usando QueryBuilder y métodos del repositorio/manager. Ejemplo:

@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface<Post> {
/**
* Indicates that this subscriber only listen to Post events.
*/
listenTo() {
return Post
}

/**
* Called before post insertion.
*/
beforeInsert(event: InsertEvent<Post>) {
console.log(`BEFORE POST INSERTED: `, event.entity)
}
}

Puedes implementar cualquier método de EntitySubscriberInterface. Para escuchar cualquier entidad, simplemente omite el método listenTo y usa any:

@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface {
/**
* Called after entity is loaded.
*/
afterLoad(entity: any) {
console.log(`AFTER ENTITY LOADED: `, entity)
}

/**
* Called before query execution.
*/
beforeQuery(event: BeforeQueryEvent<any>) {
console.log(`BEFORE QUERY: `, event.query)
}

/**
* Called after query execution.
*/
afterQuery(event: AfterQueryEvent<any>) {
console.log(`AFTER QUERY: `, event.query)
}

/**
* Called before entity insertion.
*/
beforeInsert(event: InsertEvent<any>) {
console.log(`BEFORE ENTITY INSERTED: `, event.entity)
}

/**
* Called after entity insertion.
*/
afterInsert(event: InsertEvent<any>) {
console.log(`AFTER ENTITY INSERTED: `, event.entity)
}

/**
* Called before entity update.
*/
beforeUpdate(event: UpdateEvent<any>) {
console.log(`BEFORE ENTITY UPDATED: `, event.entity)
}

/**
* Called after entity update.
*/
afterUpdate(event: UpdateEvent<any>) {
console.log(`AFTER ENTITY UPDATED: `, event.entity)
}

/**
* Called before entity removal.
*/
beforeRemove(event: RemoveEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} REMOVED: `,
event.entity,
)
}

/**
* Called after entity removal.
*/
afterRemove(event: RemoveEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} REMOVED: `,
event.entity,
)
}

/**
* Called before entity removal.
*/
beforeSoftRemove(event: SoftRemoveEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} SOFT REMOVED: `,
event.entity,
)
}

/**
* Called after entity removal.
*/
afterSoftRemove(event: SoftRemoveEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} SOFT REMOVED: `,
event.entity,
)
}

/**
* Called before entity recovery.
*/
beforeRecover(event: RecoverEvent<any>) {
console.log(
`BEFORE ENTITY WITH ID ${event.entityId} RECOVERED: `,
event.entity,
)
}

/**
* Called after entity recovery.
*/
afterRecover(event: RecoverEvent<any>) {
console.log(
`AFTER ENTITY WITH ID ${event.entityId} RECOVERED: `,
event.entity,
)
}

/**
* Called before transaction start.
*/
beforeTransactionStart(event: TransactionStartEvent) {
console.log(`BEFORE TRANSACTION STARTED: `, event)
}

/**
* Called after transaction start.
*/
afterTransactionStart(event: TransactionStartEvent) {
console.log(`AFTER TRANSACTION STARTED: `, event)
}

/**
* Called before transaction commit.
*/
beforeTransactionCommit(event: TransactionCommitEvent) {
console.log(`BEFORE TRANSACTION COMMITTED: `, event)
}

/**
* Called after transaction commit.
*/
afterTransactionCommit(event: TransactionCommitEvent) {
console.log(`AFTER TRANSACTION COMMITTED: `, event)
}

/**
* Called before transaction rollback.
*/
beforeTransactionRollback(event: TransactionRollbackEvent) {
console.log(`BEFORE TRANSACTION ROLLBACK: `, event)
}

/**
* Called after transaction rollback.
*/
afterTransactionRollback(event: TransactionRollbackEvent) {
console.log(`AFTER TRANSACTION ROLLBACK: `, event)
}
}

Asegúrate de que la propiedad subscribers esté configurada en tus DataSourceOptions para que TypeORM cargue tu suscriptor.

Event Object

Exceptuando listenTo, todos los métodos de EntitySubscriberInterface reciben un objeto de evento que tiene las siguientes propiedades base:

  • dataSource: DataSource - DataSource usado en el evento.

  • queryRunner: QueryRunner - QueryRunner usado en la transacción del evento.

  • manager: EntityManager - EntityManager usado en la transacción del evento.

Consulta cada interfaz de Event para ver propiedades adicionales.

Ten en cuenta que event.entity puede no contener necesariamente la(s) clave(s) primaria(s) cuando se usa Repository.update(). Solo estarán disponibles los valores proporcionados como parciales de la entidad. Para que las claves primarias estén disponibles en los suscriptores, puedes pasar explícitamente el valor o los valores de la clave primaria en el objeto literal de entidad parcial o usar Repository.save(), que realiza una recarga.

await postRepository.update(post.id, { description: "Bacon ipsum dolor amet cow" })

// post.subscriber.ts
afterUpdate(event: UpdateEvent<Post>) {
console.log(event.entity) // outputs { description: 'Bacon ipsum dolor amet cow' }
}

Nota: Todas las operaciones de base de datos en los escuchas de eventos suscritos deben realizarse usando la instancia queryRunner o manager del objeto de evento.