I have the following effect:
public sendData$ = createEffect(() =>
this.actions$.pipe(
ofType(actions.sendData),
concatLatestFrom(() => [
this.store.select(selectBike),
this.store.select(selectCar),
]),
concatMap(
([
,
selectedCar,
selectedBike,
]: [
TypedAction<string>,
boolean,
boolean
]) => {
const actionsArray: Action[] = [];
if (selectedCar) {
actionsArray.push(actions.addCar());
} else {
actionsArray.push(actions.removeCar());
}
if (selectedBike) {
actionsArray.push(actions.addBike());
} else {
actionsArray.push(actions.removeBike());
}
... // More products
return actionsArray;
}
)
)
Effects and services look similar for all products, so I just put for one product for reference:
EFFECTS:
@Injectable()
export class CarsEffects {
public addCar$ = createEffect(() =>
this.actions$.pipe(
ofType(addCar),
concatLatestFrom(() => [this.store.select(selectCar)]),
concatMap(([, car]: [TypedAction<string>, Car]) =>
this.carService.selectCar(car).pipe(
map(() => addCarSuccess()),
catchError(() => [addCarFailure()])
)
)
)
);
public removeCar$ = createEffect(() =>
this.actions$.pipe(
ofType(removeCar),
concatMap(() =>
this.carService.removeCar().pipe(
map(() => removeCarSuccess()),
catchError(() => [removeCarFailure()])
)
)
)
);
constructor(
private actions$: Actions,
private store: Store,
private carService: CarService
) {}
}
SERVICE:
@Injectable({
providedIn: 'root',
})
export class CarsService {
constructor(private http: HttpClient) {}
public selectCar(car: Car): Observable<any> {
const selectCarUrl = `${getApiUrl()}car/select`;
return this.http.post<ApiResponse>(selectCarUrl, {
car_id: car.id,
});
}
public removeCar(): Observable<any> {
const removeCarUrl = `${getApiUrl()}car/remove`;
return this.http.delete<ApiResponse>(removeCarUrl, {});
}
}
The problem is, that all requests are being sent at the same time. I want to send them one after another completes (or fail). I tried a lot with concatMap and other operators, but none of them appears to be working.
How can I fix my code so requests will be sent one after another?
The only workaround (temporary and ugly) was to add the delay in the return:
...
return actionsArray;
}
),
concatMap((value: Action) => of(value).pipe(delay(500)))
I would like to remove the delay and send each request after previous completes. Is it even possible? I know that better solution would be to have one endpoint for updating all products, but for now I am looking an answer for this specific problem.
all requests are being sent at the same time
? User clicks on a button and a car is removed, clicks on another button and a car gets added and so on. So the requests are not sent all at the same time. Or do you want to implement some kind of request throttling functionality on the client side?