• Empleos
  • Sobre nosotros
  • profesionales
    • Inicio
    • Empleos
    • Cursos y retos
  • empresas
    • Inicio
    • Publicar vacante
    • Nuestro proceso
    • Precios
    • Evaluaciones
    • Nómina
    • Blog
    • Comercial
    • Calculadora de salario

0

224
Vistas
BehaviorSubject: mutating current value between subscriptions

Assume I have BehaviorSubject with User interface:

interface User {
  firstName: string;
  lastName: string;
}

let user: User = {
  firstName: 'Cuong',
  lastName: 'Le',
};

let bs = new BehaviorSubject<User>(user);

There are two subsciptions, sub1 tried to change the first name. Sub2 subscribes later and user object has first name changed also as the sub1 did change it before:

let sub1 = bs.subscribe((u) => {
  u.firstName = 'An';

  console.log(u);
});

let sub2 = bs.subscribe((u) => {
  console.log(u);
});

it's hard to debug when this case happens in big Angular application. How we make the value immutable when subscribing?

I am looking deep immutable solution to prevent code somewhere else to change the data instead of the shadow one

almost 3 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

Using this answer and wrapping your type in this Immutable utility type should solve your problem. Unlike the readonly keyword or ReadOnly utility type, the Immutable interface in this answer will recursively makes all properties read only.

interface User {
  firstName: string;
  lastName: string;
  address: { 
    street: string;
  } 
}

let user: User = {
  firstName: 'Cuong',
  lastName: 'Le',
  address: { 
    street: '123 Sesame St.'
  }
};

let bs = new BehaviorSubject<Immutable<User>>(user);

let sub1 = bs.subscribe((u) => {
  u.address.street = '456'; //<-- Cannot assign to 'street' because it is a read-only property.
  console.log(u);
});
almost 3 years ago · Juan Pablo Isaza Denunciar

0

You can use the utility type Readonly<T> to mark the type on the BehaviorSubject as Readonly<User> instead of User:

let bs = new BehaviorSubject<Readonly<User>>(user);

Now, TS will warn you when you try to modify:

screenshot

Cannot assign to 'firstName' because it is a read-only property. (2540)

almost 3 years ago · Juan Pablo Isaza Denunciar

0

This is a problem I've had to solve several times. As long as you are passing simple non-circular objects through the subject this solution should work.

The one requirement is that you utilize the lodash library, which supports a very fast deep copy (no reference copies). I've looked everywhere and I've yet to find one that is faster.

let bs = (new BehaviorSubject<User>(user)).pipe(    
     map((userData) => _.cloneDeep(userData)) 
);

I've used this on fairly large state objects and I've always been impressed by how quickly it is able to perform copies. The implication here is that any emission coming out of the subject is a copy of the original, so changes happen in isolation and will never be able to trail back to the source.

almost 3 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recomiéndame algunas ofertas
Necesito ayuda