仅在第二次触发源后才发生重新订阅

时间:2019-09-03 18:23:11

标签: javascript rxjs

我正在尝试使用发送事件和撤消事件来组成流。发送消息后,您可以撤消消息并将发送的消息返回到文本字段中,延迟3秒。如果您开始撰写新邮件,则应该在发送的邮件之前添加邮件。

到目前为止,我已经设法创建了延迟的发送和撤消功能。发生问题,当我发送一条消息,撤消它,然后在不触摸输入的情况下再次发送它时,我需要更改输入值才能重新发送该消息,但无法重新发送已还原的消息。 / p>

尝试了一些变通方法,例如在文本区域中分配输入事件,或在可观察到的消息上调用next,这两种方法均在还原功能中进行。他们都没有工作。

textarea.addEventListener('input', event => message$.next(event.target.value))
send.addEventListener('click', () => textarea.value = '')

const sendEvent$ = fromEvent(send, 'click')
const undoEvent$ = fromEvent(undo, 'click')
const message$ = new Subject()
let cache = []

sendEvent$
  .pipe(
    withLatestFrom(message$, (_, m) => m),
    tap(m => cache.push(m)),
    delay(3000),
    takeUntil(undoEvent$.pipe(
      tap(restore)
    )),
    repeatWhen(complete => complete)
  )
  .subscribe(x => {
    console.log(x)
    cache = []
  })

function restore() {
  if (!textarea.value) {
    const message = cache.join('\n')
    textarea.value = message
    cache = []
  }
}

链接示例:https://stackblitz.com/edit/rxjs-undo-message

2 个答案:

答案 0 :(得分:0)

订阅者可以正常工作,只是当message$触发时您的undoEvent$不会被更新。但是,该值将设置为空字符串。

如果您撤消操作,然后键入然后再次发送,您会发现它也第一次起作用。

您要做的是将message$设置为textarea的值,然后它就会起作用。

答案 1 :(得分:0)

还原功能中几乎存在问题。还原时,不会触发“ onInput”事件。因此,您的消息队列基本上不会与恢复的项目排队。 @webber给出的建议可以在其中传递消息$ .next(message),这是正确的,这就是您需要做的。

但是问题是您如何精确设置它。您可以通过restore()中的setTimeout间隔设置值,以便您的takeUntil()完成,然后将该值排队在Subject中

function restore() {
  if (!textarea.value) {
    const message = cache.join('\n')
    textarea.value = message
    cache = []
    setTimeout(function(){
      message$.next(message)
    },3000)    
  }
}

(或) 您可以删除

textarea.addEventListener('input', event => message$.next(event.target.value))

并将发送事件处理程序更改为以下内容。

send.addEventListener('click', () => {
  message$.next(textarea.value);
  textarea.value =''
})