Home > OS >  RxJS and TypeORM: uncontrolled saving of objects using iif()
RxJS and TypeORM: uncontrolled saving of objects using iif()

Time:11-09

I am implementing a findOrSave method for an ORM entitiy and wanted to combine the observables using rxjs functions concatMap and iif.

However, somehow my code doesn't work:

return from(this.repository.findOne({ where: { label: ILike('%'   title   '%') } })).pipe(concatMap(ge => {
  return iif(() => !!ge, of(ge), from(this.repository.save({label: title})));
}))

I have a non-key but unique value such as label and want to retrieve the entitiy using findOne. If findOne returns an entity, it should be returned. Else it should be saved and the stored entitiy should be returned.

While the findOne seems to work perfectly, somehow the save method is called even if the first argument of iif returns false.

I cannot really grasp this, since this snippets works:

return from(this.repository.findOne({ where: { label: ILike('%'   title   '%') } })).pipe(concatMap(ge => {
            return iif(() => !!ge, of(ge), new Observable<GreaterEntity>(subs => {
                from(this.repository.save({label:title})).subscribe(v => {
                    console.log('Saving id ' v.id)
                    subs.next(v);
                })
            }));
        }))

If someone could point me to the mistake I made, I'd be very grateful :)

CodePudding user response:

The problem is that when are calling iif, you pass from(this.repository.save({label: title})). This immediately invokes this.repository.save() without waiting for any subscription.

To avoid this, you can use defer.

from(
  this.repository.findOne({ where: { label: ILike('%'   title   '%') } })
).pipe(
  concatMap(ge => iif(
    () => !!ge, 
    of(ge), 
    defer(() => from(this.repository.save({label: title})))
  ))
)

The callback in defer is only invoked when something subscribes to it.

  • Related