我正在尝试检测mousedown
事件是否在mouseup
之前保持一段时间。
我在使用fromEvent()
创建的Observable上使用timeout()来执行此操作,但超时会返回两个Observable。
下面,如果在1秒内触发mousedown
,订阅流将返回事件,但它也会返回1.
var mousedown = Rx.Observable.fromEvent(target, 'mousedown');
var stream = mousedown.timeout(1000, Rx.Observable.return(1));
var sub = stream.subscribe(
function (x) {
console.log('Next: '+x);
},
function (err) {
console.log('Err: '+err);
},
function () {
console.log('Complete');
}
);
但是,这可以按预期工作:
var source = Rx.Observable.return(42)
.delay(200)
.timeout(1000, Rx.Observable.return(1));
我希望这段代码能够运作:
var mousedown = Rx.Observable.fromEvent(target, 'mousedown');
var mouseup = Rx.Observable.fromEvent(target, 'mouseup');
var clickhold = mousedown
.flatMap(function (){
return mouseup.timeout(1000, Rx.Observable.return('hold'));
})
.filter(function (x) {
return x === 'hold';
});
clickhold.subscribe(
function (x) {
console.log('Next: '+x);
},
function (err) {
console.log('Err: '+err);
},
function () {
console.log('Complete');
}
);
答案 0 :(得分:6)
我没有使用timeout
,而是使用了delay
和takeUntil
:
var target,
mousedown,
mouseup;
target = document.querySelector('input');
mousedown = Rx.Observable.fromEvent(target, 'mousedown');
mouseup = Rx.Observable.fromEvent(target, 'mouseup');
var clickhold = mousedown
.flatMap(function(){
// Triggered instantly after mousedown event.
return Rx.Observable
.return('hold')
.delay(1000)
// Discards the return value if by the time .delay() is complete
// mouseup event has been already completed.
.takeUntil(mouseup);
});
clickhold.subscribe(
function (x) {
console.log('Next: ' + x);
},
function (err) {
console.log('Err: ' + err);
},
function () {
console.log('Complete');
}
);

<script src='https://rawgit.com/Reactive-Extensions/RxJS/v.2.5.3/dist/rx.all.js'></script>
<input type='button' value='Button' />
&#13;
答案 1 :(得分:1)
您自己想出了一个很好的解决方案。这就是我要改变的地方:
timer(...).takeUntil(...).select(...)
)移出flatMap
,因此不会为每个鼠标按下重新分配。你已经完成了其余的工作。对于我的使用,我通常会保留原始的mousedown
事件并使用该事件代替'hold'
。这需要returnValue
和delay
,而不是timer
和select
。
var target,
mousedown,
mouseup;
target = document.querySelector('input');
mousedown = Rx.Observable.fromEvent(target, 'mousedown');
mouseup = Rx.Observable.fromEvent(target, 'mouseup');
var clickhold = mousedown
.flatMap(function (e) {
return Rx.Observable
.return(e)
.delay(1000)
.takeUntil(mouseup);
});
clickhold.subscribe(function (x) {
console.log('onNext: ', x);
});
&#13;
<script src='https://rawgit.com/Reactive-Extensions/RxJS/v.2.5.3/dist/rx.all.js'></script>
<input type='button' value='Button' />
&#13;
或者,对于一种完全不同的方法......
var Observable = Rx.Observable,
fromEvent = Observable.fromEvent.bind(Observable, target),
holdDelay = Observable.empty().delay(1000);
Observable
.merge(
[
fromEvent('mouseup')
.map(empty),
fromEvent('mousedown')
.map(Observable.returnValue)
.map(holdDelay.concat.bind(holdDelay))
]
)
.switchLatest();
好的,这很奇怪。我真的只是把它当作食物,并且要表明这可以通过多种不同的方式来完成。