I have some difficulties with some rxjs calls and I could use some help. My problems is to parcours a list of ids, make an async call for each id and then pass on the next id once this async call is finish. Unfortunaly I did not manage to find a proper solution yet.
Here my code so far:
import { from, interval, of, Subject, timer } from 'rxjs';
import { concatMap, filter, flatMap, map, take } from 'rxjs/operators';
const callFinised$ = new Subject();
const makeAsyncCall = val => {
console.log('start call for ', val);
interval(1000)
.pipe(take(1))
.subscribe(() => {
callFinised$.next(true);
console.log('call finished for ', val);
});
};
from(['id1', 'id2'])
.pipe(
concatMap(val => {
return of(val).pipe(
flatMap(() => {
makeAsyncCall(val);
return callFinised$;
}),
filter(callFinised => callFinised === true),
take(1),
map(() => {
return val + '_updated';
})
);
})
)
.subscribe(finalVal => console.log('finalVal', finalVal));
Here the stackblitz associated: stackblitz
The second id is emited before the first async is finished, so I'm a bit lost.
Best regards
Here's a version of your code that (I think) does what you're after.
const makeAsyncCall = val => defer(() => {
console.log('start call for ', val);
return timer(1000).pipe(
map(_ => true),
tap(_ => console.log('call finished for ', val))
);
});
from(['id1', 'id2']).pipe(
concatMap(id => makeAsyncCall(id).pipe(
filter(callFinished => callFinished === true),
map(_ => id + '_updated')
))
).subscribe(finalVal => console.log('finalVal', finalVal));
Defer doesn't accomplish anything for you in the code above since you call makeAsyncCall
at basically the same time you subscribe
to the returned observable.
However, creation and subscription to Observables are different things.
In the following code, I create all the Observables first and then afterward I concatenate them and call them one after another. Without defer, this code wouldn't output what you're expecting.
const idCalls = ["id1", "id2"].map(id =>
makeAsyncCall(id).pipe(
filter(callFinished => callFinished === true),
map(_ => id + '_updated')
)
);
concat(...idCalls).subscribe(
finalVal => console.log('finalVal', finalVal)
);