This repository was archived by the owner on Dec 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
2 flaky todos
Gregor Woiwode edited this page May 6, 2024
·
13 revisions
- 1. Map API
todos
correctly - 2. Optimize requests
- 3. Fetch todos frequently
- 4. Retry fetching todos
- 5. Retry fetching todos with delay
- 6. Control display of new todos (Handle Back pressure)
- 7. Allow reloading when updates are available
- 8. Configure polling interval
- 9. Toggle polling
- 10. Check settings changes
💁♂️ Please make sure that you have started the Backend and the Client to check the impact of your changes.
- Open up
apps/client/src/app/todos/todo.service.ts
- In
query()
, use the map-Operator to convert the todo coming from the API
- Use the helper methods of
Toolbelt
to convert the todos.
// todo.service.ts > TodoService > query
map(todos => todos.map(todoFromApi => this.toolbelt.toTodo(todoFromApi)) // yields Todo for client
- Open up
apps/client/src/app/todos/todo.service.ts
- In
loadFrequently()
, apply the right operator to share the stream among multiple subscribers.
- possible operators:
share
,shareReplay
- Open up
apps/client/src/app/todos/todo.service.ts
- In
loadFrequently()
, set up an interval that fetches todos every 5 seconds.
- possible operators:
timer
,interval
,exhaustMap
,switchMap
,concatMap
- set up an interval stream
- switch from the interval to the stream loading todos
- https://rxmarbles.com/
- Open up
apps/client/src/app/todos/todo.service.ts
- In
loadFrequently()
, introduce a retry-mechanism that repeats loading todos if an error occurs.
- possible operators:
retry
- Open up
apps/client/src/app/todos/todo.service.ts
- In
loadFrequently()
, introduce a retry-mechanism that waits two several seconds before the todos get loaded again - Important
- possible operators:
retryWhen
,delay
// ...
retryWhen(errors => errors.pipe(delay(/* ... your delay in ms ... */));
- Currently, todos get updated automatically. The problem is that the user might not have finished reading and gets confused by an unexpected update.
- That's why the user should be in charge to update the view by pressing a button
- Open up
apps/client/src/app/todos/todos.component.ts
- In
ngOnInit
, configure a stream that emits the latest todos when ever the buttonRELOAD
has been pressed.
- possible operators:
merge
,withLatestFrom
- The stream
update$$
emits whenever the RETRY-Button is clicked. - You need to combine to streams of todos
- Initially loaded todos stream
- Button-Click-Stream that maps into the latest todos loaded from the API.
// Load todos initially
this.todosInitial$ = this.todosSource$.pipe(first());
// Retrieve most recent todos if button has been clicked
this.todosMostRecent$ = this.update$$.pipe(
withLatestFrom(this.todosSource$),
map((result): [MouseClickEvent, Todo[]] => /* ... map to todos ... */)
)
// show initially loaded todos & newest todos after button-click to user
this.todos$ = merge(this.todosInitial$, this.todosMostRecent$)
- Currently the button is displayed all the time
- The user can press it no matter if there are new todos loaded.
- Make the button only show up if updates are available from the server.
- possible operators:
merge
,map
- When
update$$
emits, the button should be hidden - When
todoSource$
emits, the button should be displayed
this.show$ = // true if todoSource$ emits
this.hide$ = // false if update$$ emits
this.showReload$ = // merge show$ & hide$
- Open
apps/client/src/app/todos/todo.service.ts
- In
loadFrequently
, consume the settings stream fromtodo-settings.service.ts
and use the incoming value ofpollingInterval
loading todos - Open your app & change the interval in the settings dialogue. Notice, that changing the settings instantly has an effect in which interval new todos are loaded.
- possible operators:
switchMap
- Open
apps/client/src/app/todos/todo.service.ts
- In
loadFrequently
, consume the settings stream fromtodo-settings.service.ts
and use the incoming value ofpollingInterval
loading todos - Open your app & enable/disable polling. Notice, that loading the stops/starts right after applying the change.
- Open
apps/client/src/app/todos/todo.service.ts
- In
loadFrequently
, only restart the polling, when a value in the settings actually changed - Test it in the app
- Open settings dialogue
- Click in the interval input field
- Press Enter
// todos-settings.service.ts
distinctUntilChanged((previous, current) => /* ... apply filter logic here ... */)