I have a CreateReviewForm with reCaptcha and I have 3 streams for it:
addReview
) (1st observable). Everytime when this action is triggered I have to call this.recaptchaV3Service.execute()
method which returns observable with token (string) (2nd observable). And then using this token I have to call API method for creating review this.reviewApiService.create({ ...review, recaptchaValue: token })
which returns observable with created review (3rd observable)First I tried it with combineLatest
and it didn't work like I expected. Method for getting token emited value only when I clicked "Add Review" btn first time. All next times it didn't emit any value (withLatestFrom
worked in the same way. I tried it also)
createReview$ = combineLatest([
this.actions$.pipe(
ofType(ReviewsDialogActions.addReview)
),
this.recaptchaV3Service.execute('AddREview')
]).pipe(exhaustMap(([{ review }, token]) =>
this.reviewApiService.create({ ...review, recaptchaValue: token })))
.pipe(
map(createdReview => ReviewsDialogApiActions.createReviewSuccess({ createdReview, companyId: createdReview.company.id })),
catchError(error => {
debugger;
return observableOf(ReviewsDialogApiActions.createReviewError({ error: error.error.message.join(', ') }))
})
)
I combined it all with concatMap
and exhaustMap
and it works but I don't like how it looks and I don't think it should look like this
createReview$ = createEffect((): any => {
let reviewFormData = {};
return this.actions$.pipe(
ofType(ReviewsDialogActions.addReview),
concatMap(({ review }) => {
reviewFormData = review;
return this.recaptchaV3Service.execute('AddREview');
}),
exhaustMap((token) => this.reviewApiService.create({ ...<Review>reviewFormData, recaptchaValue: token })
.pipe(map(createdReview => ReviewsDialogApiActions.createReviewSuccess({ createdReview, companyId: createdReview.company.id })),
catchError(error => {
return observableOf(ReviewsDialogApiActions.createReviewError({ error: error.error.message.join(', ') }))
})))
)
}
Please help which is the best combination here for rxJs operators?
You could use the pipeable operator combineLatestWith
like this:
createReview$ = createEffect(() => this.actions$.pipe(
ofType(ReviewsDialogActions.addReview),
combineLatestWith(this.recaptchaV3Service.execute('AddREview')),
exhaustMap(([reviewFormData, token]) => this.reviewApiService.create(..)
...
)
)
Cheers