1

From an x.component.ts I call getSomething() in y.service.ts. I subscribe to getSomething() because is returns an observable. The thing is that before the .subscribe() I have an object that has 4 elements inside, one of which is an array of number arrays (number[][]), and after the .subscribe that same array is now empty.

x.component.ts

this.y
      .getSomething()
      .pipe(
        //make an observable to pass to child component 
        tap(data => (this.pautaFinal$ = of(data))),
        // This object is just for development purpose
        tap(data => (this.pautaFinal = data)),
        // This is to change the number[][] object into a number[][][]
        // I need it that way
        tap(
          data =>
            (this.escalaPorcionada = this.transformEscala(
              data.escala.escalaArr,
              10
            ))
        )
      )
      .subscribe();

// Makes an array of number arrays, into an array of arrays of chunkSize number arrays.
transformEscala(escala: number[][] = [], chunkSize: number): number[][][] {
    let results: number[][][] = [];
    while (escala.length) {
      results.push(escala.splice(0, chunkSize));
    }
    return results;
  }

In this x.component I've also tried, instead of the third tap, a map(data => data.escala.escala) and then `.subscribe(data => this.escalaPorcionada = this.transformEscala(data, 10).

y.service.ts
  getSomething(): Observable<Pauta> {
    let admin: DatosAdmin;
    let escala: Escala;
    let rubrica: Rubrica;
    let criterios: Criterios;
    this.datosAdminAcumul$.subscribe(datos => (admin = datos));
    this.escalaAcumul$.subscribe(datos => (escala = datos));
    this.rubricaAcumul$.subscribe(datos => (rubrica = datos));
    this.criteriosAcumul$.subscribe(datos => (criterios = datos));

    let user = JSON.parse(localStorage.getItem("user"));

    // Ultimos datos que agregar a la pauta.
    let extras = {
      usuarioModificacion: user.id
    };

    const pautaFinal: Pauta = {
      datosAdmin: admin,
      criterios: criterios,
      rubrica: rubrica,
      escala: escala,
      extras: extras
    };
    return of(pautaFinal);
  }

This is the function im calling in y.service.ts. It has some observables that are in the same service, it subscribes to them, gets some values, assign them to something else and then all those, put them inside a pautaFinal object, and that's what I return as an observable.

What have i tried: I've checked the chrome debugger and before the subscribe the array exists, after, it is empty.

This is the value of escalaArr inside the observable this.escalaAcumul$ (from y.service) Before .subscribe() (escalaArr is the array that is lost)

This is after the subscribe. Just one function call after the previous image. After .subscribe()

This object has 4 more elements, and none of them change, just escalaArr.

I don't know what i'm doing wrong here. I've been stuck for a while and appreciate some help, thanks.

1 Answer 1

1

Try to clone the object handed in by the Observable before processing it. This way you break the 'by reference'-chain of JavaScript.

this.y
  .getSomething()
  .pipe(
    //make an observable to pass to child component 
    tap(data => (this.pautaFinal$ = of(data))),
    // This object is just for development purpose
    tap(data => (this.pautaFinal = data)),
    // This is to change the number[][] object into a number[][][]
    // I need it that way
    tap(
      data =>
        (this.escalaPorcionada = this.transformEscala(
          Object.assign({}, data.escala.escalaArr), // <-- clone here to avoid changing the original
          10
        ))
    )
  )
  .subscribe();

If this does not solve the problem check whether any other component has access to the setter of your Observable.

EDIT:

Option 2:

transformEscala(escala: number[][] = [], chunkSize: number): number[][][] {
    let results: number[][][] = [];
    const clone = Object.assign({}, escala);

while (clone.length) {
  results.push(clone.splice(0, chunkSize));
}
return results;

}

Sign up to request clarification or add additional context in comments.

7 Comments

I tried map(data => deepCopy(data) as Pauta, before the first tap(), but same result.
Okay, I made an edit and added an option 2. Try to clone the object inside transformEscala()instead of inside the subscription.
You're welcome. Yes, I meant my example above where I put the Object.assign() inside the subscription()-block.
Unfortunately, I have no #1 page I could recommend on this topic. Sorry. -- The important point is the fact, that the splice()-operator changes the original array. In your case the array escala. So while you're splicing and pushing you actually manipulate the array inside your service. That's why the array is empty afterwards. Here is how splice() works in general. w3schools.com/jsref/jsref_splice.asp . Using Object.assign() decouples the original object and your splice()-operation only affects your local copy. googlechrome.github.io/samples/object-assign-es6
PS: Here is an interesting post concerning 'pass-by-reference', which is what happened in your example: stackoverflow.com/questions/13104494/…
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.