0

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.

3
  • please share a simple stackblitz where you have the problem replicated and the current output, also share the expected output, require working example to proceed Commented Aug 1, 2024 at 3:32
  • What do you mean by 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? Commented Aug 2, 2024 at 12:52
  • For example, add bike and add car requests are being sent at the same time (I have a button continue). In my send data effect, I want then to be sent one after another completes. I have more items not only car and bike, so i specifically need no somehow modify my sendData effect. concatMap is not working Commented Aug 7, 2024 at 7:31

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.