admin管理员组文章数量:1290951
I know a little bit of BaconJS, but now I'm trying to learn RxJS by creating a "User is typing..." indicator. It's pretty simple, it can be explained in two simple rules:
- When the user is typing, the indicator should be immediately visible.
- When the user stops typing, the indicator should still be visible until 1 second after the user's last typing action.
I'm not sure if this is correct, but I have so far created two streams:
- One heartbeat stream that emits a
0
every second. - One stream to capture the user typing events and emit a
1
for every event.
Then I merge them together, and simply tap into the result. If it's a 1
, then I show the indicator. If it's a 0
, then I hide the indicator.
This is what that looks like:
const showTyping = () =>
$('.typing').text('User is typing...');
const showIdle = () =>
$('.typing').text('');
// 1 second heartbeats are mapped to 0
const heartbeat$ = Rx.Observable
.interval(1000)
.mapTo(0);
// user typing events are mapped to 1
const input$ = Rx.Observable
.fromEvent($('#input'), 'input')
.mapTo(1);
// we merge the streams together
const state$ = heartbeat$
.merge(input$)
.do(val => val === 0 ? showIdle() : showTyping())
.subscribe(console.log);
Here is a link to the JSBin:
,console,output
There are several problems and questions I have with this implementation:
- Sometimes when the user is typing, a
0
sneaks through, so the indicator flashes away for a split second before ing back on the next user keystroke. - It's not guaranteed that the indicator will disappear 1 second after the user stops typing. It's only guaranteed that the indicator will disappear within 1 second (which is kind of the opposite of what we want).
- Is using a heartbeat stream the correct RxJS way to do this? I have a feeling it might not be.
I have a feeling that I am pletely off-base with my implementation, I appreciate any help that you may be able to provide. Thanks.
I know a little bit of BaconJS, but now I'm trying to learn RxJS by creating a "User is typing..." indicator. It's pretty simple, it can be explained in two simple rules:
- When the user is typing, the indicator should be immediately visible.
- When the user stops typing, the indicator should still be visible until 1 second after the user's last typing action.
I'm not sure if this is correct, but I have so far created two streams:
- One heartbeat stream that emits a
0
every second. - One stream to capture the user typing events and emit a
1
for every event.
Then I merge them together, and simply tap into the result. If it's a 1
, then I show the indicator. If it's a 0
, then I hide the indicator.
This is what that looks like:
const showTyping = () =>
$('.typing').text('User is typing...');
const showIdle = () =>
$('.typing').text('');
// 1 second heartbeats are mapped to 0
const heartbeat$ = Rx.Observable
.interval(1000)
.mapTo(0);
// user typing events are mapped to 1
const input$ = Rx.Observable
.fromEvent($('#input'), 'input')
.mapTo(1);
// we merge the streams together
const state$ = heartbeat$
.merge(input$)
.do(val => val === 0 ? showIdle() : showTyping())
.subscribe(console.log);
Here is a link to the JSBin:
http://jsbin./vekixuv/edit?js,console,output
There are several problems and questions I have with this implementation:
- Sometimes when the user is typing, a
0
sneaks through, so the indicator flashes away for a split second before ing back on the next user keystroke. - It's not guaranteed that the indicator will disappear 1 second after the user stops typing. It's only guaranteed that the indicator will disappear within 1 second (which is kind of the opposite of what we want).
- Is using a heartbeat stream the correct RxJS way to do this? I have a feeling it might not be.
I have a feeling that I am pletely off-base with my implementation, I appreciate any help that you may be able to provide. Thanks.
Share Improve this question edited Jan 7, 2017 at 12:00 martin 97k26 gold badges203 silver badges235 bronze badges asked Jan 7, 2017 at 11:25 adrianmcliadrianmcli 1,9963 gold badges23 silver badges49 bronze badges2 Answers
Reset to default 10You don't even need to use two Observables and use just one with debounceTime()
. All the logic you tried to make is already present in debounceTime()
operator:
const showTyping = () =>
$('.typing').text('User is typing...');
const showIdle = () =>
$('.typing').text('');
const input$ = Rx.Observable
.fromEvent($('#input'), 'input')
.do(() => showTyping())
.debounceTime(1000)
.subscribe(() => showIdle());
See live demo: http://jsbin./cixipa/6/edit?js,console,output
You don't need a heartbeat for this, just emit change-events whenever something happens/changes:
const showTyping = () =>
$('.typing').text('User is typing...');
const showIdle = () =>
$('.typing').text('');
// user typing events
const input$ = Rx.Observable
.fromEvent($('#input'), 'input');
// user stopped typing
const stoppedTypingAfter1s$ = input$
.switchMapTo(Rx.Observable.timer(1000));
// we merge the streams together
const state$ = Rx.Observable.merge(
input$.mapTo(1),
stoppedTypingAfter1s$.mapTo(0)
)
.startWith(0)
.do(val => val === 0 ? showIdle() : showTyping())
.subscribe(console.log);
See live here.
The switchMap
, will discard any previouse 1s-timer whenever a new typing-event is emitted.
本文标签: javascriptHow to use RxJS to display a quotuser is typingquot indicatorStack Overflow
版权声明:本文标题:javascript - How to use RxJS to display a "user is typing" indicator? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741519970a2383121.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论