I am currently developing a chat application and I am looking to display bot messages sequentially with a delay between each message. This will create the illusion that the bot is typing out the messages instead of sending them all at once. I initially attempted this using RxJS but was unable to achieve the desired effect.
Check out the Stackblitz Link here.
query(): Observable<IChatResponse> {
const response = {
messages: [
{
text: 'Please provide a valid domain name',
},
{
text: 'What domain are you interested in?',
},
{
text: 'Some other messages...',
},
],
};
return of(response).pipe(
switchMap((response: any) => this.convertToStream(response))
);
}
convertToStream(data: any): Observable<IChatResponse> {
let count = 0;
const messageDelayFn = (message, index): Observable<any> => {
const loaderStart$ = of(null).pipe(
tap((_) => console.log('index ', index)),
delay(500 * index),
tap((_) => {
this.loading$.next(true);
})
);
const loaderStop$ = of(null).pipe(
delay(1000 * index),
tap((_) => {
this.loading$.next(false);
})
);
const message$ = of(message);
return concat(loaderStart$, loaderStop$, message$).pipe(share());
};
const transformedObservable = of(data).pipe(
map((chat) => {
return {
...chat,
messages: chat.messages.reduce((acc: Observable<any>[], message) => {
return [...acc, messageDelayFn(message, ++count)];
}, []),
};
})
);
return transformedObservable;
}
The expected behavior I am aiming for is as follows:
- Starts with loader for 500ms
- Loader stops
- Emits first message
- Loader starts again for 500ms (before emitting second message)
- Loader stops
- Emits second message
- ...and so on