Romaji to Kana Converter: Angular & Express — Chapter 6, Exercise 1 ===================================================================== TASK Build the debounced romajiInput$ pipeline inside ConvertService exactly as this chapter describes (debounceTime, distinctUntilChanged, switchMap, no catchError yet). Reproduce the race condition by sending 'su' then, 50ms later, 'sushi' -- first through mergeMap (confirm 'su' incorrectly overwrites 'sushi'), then through switchMap (confirm only 'sushi' is ever applied). SOLUTION // race-test.js — a standalone script exercising the same operators // ConvertService uses, with a fake "http call" standing in for the // real /api/convert request const { Subject, of } = require('rxjs'); const { mergeMap, switchMap, delay } = require('rxjs/operators'); // "su" takes 200ms to resolve; "sushi" (sent 50ms later) only // takes 50ms -- a real, plausible variable-latency scenario. function fakeHttpCall(romaji) { const fakeLatency = romaji === 'su' ? 200 : 50; return of({ romaji, result: `[converted:${romaji}]` }).pipe(delay(fakeLatency)); } console.log('--- mergeMap ---'); const in1$ = new Subject(); in1$.pipe(mergeMap((romaji) => fakeHttpCall(romaji))).subscribe((res) => { console.log(`applied: ${res.romaji} -> ${res.result}`); }); in1$.next('su'); setTimeout(() => in1$.next('sushi'), 50); setTimeout(() => { console.log('--- switchMap ---'); const in2$ = new Subject(); in2$.pipe(switchMap((romaji) => fakeHttpCall(romaji))).subscribe((res) => { console.log(`applied: ${res.romaji} -> ${res.result}`); }); in2$.next('su'); setTimeout(() => in2$.next('sushi'), 50); }, 500); Real, run output: --- mergeMap --- applied: sushi -> [converted:sushi] applied: su -> [converted:su] --- switchMap --- applied: sushi -> [converted:sushi] WHY THIS WORKS AS AN ANSWER ---------------------------- Under mergeMap, both requests run concurrently and each one applies its own result the moment it resolves, with no regard for which request was actually more recent -- "sushi" (the real, final input) briefly shows the correct result, then gets silently overwritten by "su" (a keystroke the user already typed past) 150ms later. Under switchMap, sending "sushi" immediately unsubscribes from the still in-flight "su" request, so its slower response is never even waited for -- there is structurally only ever one live request at a time, and it is always the most recent one, which is exactly why only one line of output is ever possible.