1

I am new to rxjs and am trying to do two requests. When I try to see the result, I get Observable.

copy() {
    const obj = {};

    this.create(skill)
      .pipe(
        mergeMap((res) => {
          return [res, forkJoin(this.levels.map((level) => this.level(level)))];
        }),
      )
      .subscribe((res) => {
        console.log(res);
      });
  }

level(level) {
    return this.create(level);
  }

Output: object of created skill, Observable {_isScalar: false, _subscribe: ƒ}

I get the response of the first request normally and the second one comes to me as "Observable".

Vladislav
  • 125
  • 6
  • Can you please clarify your question? What is meant by "first request" / "second request"? – BizzyBob Mar 09 '21 at 12:57
  • @BizzyBob, I need to get the answer from the first request (this.create(skill)) and use it in the second request (this.level(level)). Also receive in subscribe the response of the first request and the second request. – Vladislav Mar 09 '21 at 13:02
  • You need data from first request to make second request? – BizzyBob Mar 09 '21 at 13:06
  • @BizzyBob, yes, and get these two responses in subscribe – Vladislav Mar 09 '21 at 13:11

2 Answers2

0

ForkJoin might not be the optimal operator here. I suggest having a look at the operator decision tree. I believe you want something like this though?

 copy() {
    const obj = {};

    forkJoin(
       [
          this.create(skill),
          ...this.levels.map((level) => this.level(level))
       ]
    ).subscribe((res) => {
       console.log(res);
    });
  }

  level(level) {
    return this.create(level);
  }
Stefan
  • 160
  • 6
  • and how can I get the result of the first method and pass it to the second? – Vladislav Mar 09 '21 at 12:41
  • you need the result of `this.create(skill)` before you do `this.levels.map`? If that's the case then you don't need `forkJoin` at all. You can just use `mergeMap`. – Stefan Mar 09 '21 at 12:51
  • I also need to get the response of the first request and the second in subscribe – Vladislav Mar 09 '21 at 13:04
  • Sure thing: https://stackblitz.com/edit/h3se1f?file=index.ts – Stefan Mar 09 '21 at 13:08
  • and the last question: can I return an object with named keys for these objects? – Vladislav Mar 09 '21 at 13:19
  • Yeah. I don't see why not. I updated the stackblitz code so the levels are in an object instead of an array. – Stefan Mar 09 '21 at 13:23
  • you did not understand me, the object of these responses – Vladislav Mar 09 '21 at 13:26
  • to get an object of two responses in subscribe – Vladislav Mar 09 '21 at 13:27
  • If you want only 1 value to be emitted with the combined responses then BizzyBob's example does that. In the example I gave you, there are multiple values being emitted. Try them both and see which behaviour is better in your case. – Stefan Mar 09 '21 at 13:34
0

I'm not completely sure I understand what you're trying to do :-)

The function you pass to mergeMap() should "usually" return an observable. Currently, you are returning an array.

  • When you return array, mergeMap will simply emit each array element; which is why you receive those two emissions created skill, Observable.
  • However, if you return Observable, mergeMap will subscribe to it and emit.

I think this could work for you:

copy() {
  this.create(skill).pipe(
    mergeMap(createdSkill => forkJoin(this.levels.map(l => this.level(l))).pipe(
      map(createdLevels => ([createdSkill, createdLevels]))  
    )
  )
  .subscribe(
    ([skill, levels]) => console.log({skill, levels})
  );
}

It might be easier to follow if we break it down into smaller chunks:

createLevels() { 
    return forkJoin(this.levels.map(l => this.level(l));
}

copy() {
  this.create(skill).pipe(
    mergeMap(createdSkill => createLevels()).pipe(
      map(createdLevels => ([createdSkill, createdLevels]))  
    )
  )
  .subscribe(
    ([skill, levels]) => console.log({skill, levels})
  );
}

Looking it this way seems like we could instead build the copy() method in a simpler way:

copy(skill) {
  forkJoin(
    this.createSkill(skill),
    this.createLevels()
  )
  .subscribe(
    ([skill, levels]) => console.log({skill, levels})
  );
}
BizzyBob
  • 12,309
  • 4
  • 27
  • 51