angular - Start multiple independent requests that rely on the same emitted value of another observable - Stack Overflow

I need to start 3 independent requests in a component that rely on a value emitted by another observabl

I need to start 3 independent requests in a component that rely on a value emitted by another observable.

The first request provides an ID, once that ID is emitted I have to start 3 independent asynchronous requests which need that ID to recover the data from server.

The 3 requests should not be merged together and should remain separate so that I can be able to subscribe to each of those independent requests.

const source_id = <async_request_ID>;
const source_A = <async_request_A(ID)>;
const source_B = <async_request_B(ID)>;
const source_C = <async_request_C(ID)>;

source_id.pipe(
  operator_I_am_looking_For((id) => source_A(id), source_B(id), source_C(id))
)

source_A.subscribe(...);
source_B.subscribe(...);
source_C.subscribe(...);

Probably the best way to handle this scenario is to notify the emitted value of the first request (the ID) but I'd like to know if exists a way to handle that with some kind of operator.

I need to start 3 independent requests in a component that rely on a value emitted by another observable.

The first request provides an ID, once that ID is emitted I have to start 3 independent asynchronous requests which need that ID to recover the data from server.

The 3 requests should not be merged together and should remain separate so that I can be able to subscribe to each of those independent requests.

const source_id = <async_request_ID>;
const source_A = <async_request_A(ID)>;
const source_B = <async_request_B(ID)>;
const source_C = <async_request_C(ID)>;

source_id.pipe(
  operator_I_am_looking_For((id) => source_A(id), source_B(id), source_C(id))
)

source_A.subscribe(...);
source_B.subscribe(...);
source_C.subscribe(...);

Probably the best way to handle this scenario is to notify the emitted value of the first request (the ID) but I'd like to know if exists a way to handle that with some kind of operator.

Share Improve this question edited Mar 3 at 12:16 jonrsharpe 122k30 gold badges268 silver badges476 bronze badges asked Mar 3 at 12:15 bernoberno 2533 silver badges15 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 1

This is fairly simple:

let source_id = <async_request_ID>;
let source_A = <async_request_A(ID)>;
let source_B = <async_request_B(ID)>;
let source_C = <async_request_C(ID)>;

const shared_source_id = source_id.pipe(
  shareReplay(1) //Share the latest result for future subscribers
)

// And now simply switch map to use the ID to do follow up requests
shared_source_id.pipe(switchMap(id => source_A(id))).subscribe(...);
shared_source_id.pipe(switchMap(id => source_B(id))).subscribe(...);
shared_source_id.pipe(switchMap(id => source_C(id))).subscribe(...);

Basically you share the result of the ID request and then use this result to do follow ups. Then, switchMap() is like map() only that the return value of the function inside has to be an observable. The operator handles the subscription of the "parent" observable, so you don´t have to worry about that.

Just be aware that if your source_id fires a second time (for whatever reason) - all "children" are getting triggered again. (Should not be relevant in this case since they are all HTTP-Requests)

Read more about switchMap() here: https://rxjs.dev/api/index/function/switchMap

p.s. I kept the pseudocode style from your question, so this code probably won´t compile.

Not sure if using Observable is required but this can be solved by using signal with the help of toSignal function:

  • https://angular.dev/api/core/rxjs-interop/toSignal

You can convert your source_id to signal; source_A, source_B and source_C would then become computed/effect (depending on the usecase) which will start the request. Sketch below:

const source_id = toSignal(async_request_ID);
const source_A = computed(() => 
{
    const ID = source_id();
    return async_request_A(ID);
});
const request_A_result = await source_A();

If the function can't be async (await source_A()) you can convert the signal back to Observable using toObservable function:

  • https://angular.dev/api/core/rxjs-interop/toObservable

Based on your requirement an optimal way to handle would be by using shareReplay() operator from RxJS. It helps you replay the last 'n' values (shareReplay(n)).

import { shareReplay } from 'rxjs/operators';

const source_id$ = <async_request_ID>.pipe(
  shareReplay(1) // Cache the emitted ID. Specifying 1 since we need last value only
);

// Creation of the three sources that need the ID
const source_A$ = source_id$.pipe(
  switchMap(id => <async_request_A(id)>)
);

const source_B$ = source_id$.pipe(
  switchMap(id => <async_request_B(id)>)
);

const source_C$ = source_id$.pipe(
  switchMap(id => <async_request_C(id)>)
);

// Now you can subscribe to each independently
source_A$.subscribe(...);
source_B$.subscribe(...);
source_C$.subscribe(...);

This most likely serves your need.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745095216a4610935.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信