Browse Source

[CL-298] feat: add duplicate execution protection

CL-298-async-actions-2-0-context-string
Andreas Coroiu 2 years ago
parent
commit
b88fdb40a9
No known key found for this signature in database
GPG Key ID: E70B5FFC81DFEC1A
  1. 12
      libs/components/src/async-actions/async-actions.service.spec.ts
  2. 10
      libs/components/src/async-actions/async-actions.service.ts

12
libs/components/src/async-actions/async-actions.service.spec.ts

@ -126,7 +126,17 @@ describe("AsyncActionsService", () => { @@ -126,7 +126,17 @@ describe("AsyncActionsService", () => {
expect(action.observed).toBe(false);
});
it("ignores EmptyError and completes the action", async () => {});
it("does not execute the handler if another action is already active in the same context", async () => {
const first_action = new Subject();
const second_action = new Subject();
const origin = Symbol();
void service.execute("context", origin, () => first_action);
void service.execute("context", origin, () => second_action);
expect(first_action.observed).toBe(true);
expect(second_action.observed).toBe(false);
});
});
});

10
libs/components/src/async-actions/async-actions.service.ts

@ -57,17 +57,25 @@ export class AsyncActionsService implements OnDestroy { @@ -57,17 +57,25 @@ export class AsyncActionsService implements OnDestroy {
* - Regular functions are also supported, but the loading state will not be set. This is useful for functions that might
* need to return early.
*
* NOTE: The handler will not be executed if another action is already active in the same context.
*
* @param context A string that will be used to group the loading state of multiple async actions.
* @param origin The object that the action originated from.
* @param handler The function to execute.
* @param until An observable that will cause the action to be cancelled when it emits.
*/
async execute(
context: string | undefined,
context: string,
origin: unknown,
handler: FunctionReturningAwaitable,
until?: Observable<unknown>,
): Promise<void> {
// Access the current state directly, otherwise you can execute multiple actions in the same context
// by not awaiting the promise returned by this method.
if (this.states$.value?.[context]?.status === "active") {
return;
}
this.updateState((state) => ({ ...state, [context]: { status: "active", origin } }));
try {

Loading…
Cancel
Save