Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

2 flaky todos

Gregor Woiwode edited this page May 6, 2024 · 13 revisions

Contents

💁‍♂️ Please make sure that you have started the Backend and the Client to check the impact of your changes.

1. Map API todos correctly

  • Open up apps/client/src/app/todos/todo.service.ts
  • In query(), use the map-Operator to convert the todo coming from the API

Hint

  • 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

2. Optimize requests

  • Open up apps/client/src/app/todos/todo.service.ts
  • In loadFrequently(), apply the right operator to share the stream among multiple subscribers.

Hint

  • possible operators: share, shareReplay

3. Fetch todos frequently

  • Open up apps/client/src/app/todos/todo.service.ts
  • In loadFrequently(), set up an interval that fetches todos every 5 seconds.

Hint

  • possible operators: timer, interval, exhaustMap, switchMap, concatMap
  • set up an interval stream
  • switch from the interval to the stream loading todos
  • https://rxmarbles.com/

4. Retry fetching todos

  • Open up apps/client/src/app/todos/todo.service.ts
  • In loadFrequently(), introduce a retry-mechanism that repeats loading todos if an error occurs.

Hint

  • possible operators: retry

5. Retry fetching todos with delay

  • 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

Hint

  • possible operators: retryWhen, delay
// ...
retryWhen(errors => errors.pipe(delay(/* ... your delay in ms ... */));

6. Control display of new todos (Handle Back pressure)

  • 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 button RELOAD has been pressed.

Hint

  • 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$)

7. Allow reloading when updates are available

  • 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.

Hint

  • 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$

8. Configure polling interval

  • Open apps/client/src/app/todos/todo.service.ts
  • In loadFrequently, consume the settings stream from todo-settings.service.ts and use the incoming value of pollingInterval 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.

Hint

  • possible operators: switchMap

9. Toggle polling

  • Open apps/client/src/app/todos/todo.service.ts
  • In loadFrequently, consume the settings stream from todo-settings.service.ts and use the incoming value of pollingInterval loading todos
  • Open your app & enable/disable polling. Notice, that loading the stops/starts right after applying the change.

10. Check settings changes

  • 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

Steps to reproduce

  • Open settings dialogue
  • Click in the interval input field
  • Press Enter

Hint

// todos-settings.service.ts
distinctUntilChanged((previous, current) => /* ... apply filter logic here ... */)