angular - "Användaren skriver" lätt RXJS-implementation
Jag arbetar för närvarande med att implementera en "Användaren skriver"-funktion för ett chattrum med flera användare. Med min begränsade kunskap om RXJS lyckades jag ta fram följande kodsnutt som uppfyller minimikraven för "Användaren skriver"-funktionen:
this.messageForm.message.valueChanges
.pipe(
tap(() => this.convoService.isUserTyping(true)),
debounceTime(500),
map(() => this.convoService.isUserTyping(false))
)
.subscribe();
Denna implementation är dock inte ideal eftersom den genererar för många förfrågningar till servern. Mitt mål är att begränsa förfrågningarna till 2, och genom att använda RXJS-operatörer skapa följande beteenden:
- Skicka endast en förfrågan vid första knapptryckningen
- Ignorera alla efterföljande knapptryckningar
- Vänta en X mängd tid efter vad som kan vara den sista tangenttryckningen
- Återställ nedräkningen om en ny tangenttryckning sker innan nedräkningen går ut
- Skicka en förfrågan när nedräkningen har löpt ut
Svar #1
Här är ett sätt att uppnå det utan bieffekter:
const typing$ = this.messageForm.message.valueChanges.pipe(
switchMap(() => concat(
of(true),
of(false).pipe(delay(500)),
)),
distinctUntilChanged(),
)
Du kan använda det för att utföra dina förfrågningar. Om isUserTyping är en fire-and-forget, kan du bara göra
typing$.subscribe(typing => this.convoService.isUserTyping(typing));
Om det är en asynkron förfrågan (och returnerar ett observerbart) skulle jag helst gå med detta:
typing$.pipe(
concatMap(typing => this.convoService.isUserTyping(typing))
).subscribe();
På så sätt säkerställer du att alla förfrågningar utförs i ordningsföljd, vilket undviker problem med fel ordning i situationer med hög latens¹.
¹ Om latens verkligen var ett problem skulle detta kräva ännu mer arbete med buffring för att istället undvika att trycka tillbaka förfrågningarna för mycket, men detta är i alla fall utanför omfattningen för denna fråga.
