Here is a scenario of 3 typical step groups
- preparation work
- retrieving data
- cleanup work
I am looking for an optimal arrangement of handing these steps that are set in an array (see below).
Conditions:
Important: The first two step groups must be cancelable at any point / any time by an event or Subject or similar (e.g. triggered by user's click).
If the cancel/stop is triggered, steps of group 3 still need to run to do the cleanup work
1. preparation work:
1.1. action steps of this group 1 must be executed in order one by one
1.2. all steps are executed, unless canceled
1.3. (can be coded any way - as function, Observable, Promise, etc.)
2. retrieving data
2.1. executes after preparation work steps (1)
2.2. this step uses an API, which returns the data as: Promise<T[]>
2.3. the result data is returned to caller/subscriber immediately (does not wait for cleanup work)
2.4. returned result must be again as: Promise<T[]>
3. cleanup work
3.1. starts after step 2
3.2. may run asynchronously / at any time / later, but after steps 1 and 2
3.3. the steps of group 3 must be executed in order one by one
3.4. (can be coded any way - as function, Observable, Promise, etc.)
Here is my skeleton code that needs revision especially the code inside the method:
handleDataRequest()
import { Injectable } from '@nestjs/common';
import { from, Subject } from 'rxjs';
import { filter, map, switchMap, mergeMap,subscribeOn, take, takeUntil, } from 'rxjs/operators';
export interface ActionStep {
id: string,
taskGroup: number // 1 = Prep.Work, 2 = Data, 3 = Cleanup
// etc.
}
export const ActionSteps: ActionStep[] = [
{ id: 'PrepWork1', taskGroup: 1 },
{ id: 'PrepWork2', taskGroup: 1 },
{ id: 'PrepWork3', taskGroup: 1 },
{ id: 'Data', taskGroup: 2 },
{ id: 'Cleanup1', taskGroup: 3 },
{ id: 'Cleanup2', taskGroup: 3 },
]
@Injectable()
export class DataRequestService<T> {
public requestCanceled$: Subject<boolean>;
handleDataRequest(actionSteps: ActionStep[]): Promise<T[]> {
const actionSteps$ = from(actionSteps);
actionSteps$.pipe(
filter(step => step.taskGroup === 1), // 1 = Prep.Work
takeUntil(this.requestCanceled$),
map((step: ActionStep,) => this.prepWork(step)));
const result = actionSteps$.pipe(
filter(step => step.taskGroup === 2), // 2 = Data
takeUntil(this.requestCanceled$),
map((step: ActionStep) => this.getData(step)));
actionSteps$.pipe(
filter(step => step.taskGroup === 3), // 3 = Cleanup
map((step: ActionStep,) => this.cleanupWork(step)));
return result;
}
private prepWork(param) {
// doing prep. work ...
}
private getData<T>(param): Promise<T[]> {
let data: Promise<T[]>;
// getting data ...
return data;
}
private cleanupWork(param) {
// doing cleanup ...
}
}