web/laminar

EventStream 의 flatMap vs combineWithFn

wefree 2022. 10. 1. 17:37

코드

package com.github.windbird.playweb

import com.raquo.laminar.api.L._
import org.scalajs.dom

object Main {
  def main(args: Array[String]): Unit = {
    val buttonA  = button("A")
    val buttonAE = buttonA.events(onClick.mapTo(scala.math.random())).debugLog()
    val buttonB  = button("B")
    val buttonBE = buttonB.events(onClick.mapTo(scala.math.random())).debugLog()

//    val c: EventStream[String] = buttonAE.combineWithFn(buttonBE)((x, y) => s"$x + $y")
    val c: EventStream[String] = for {
      x <- buttonAE
      y <- buttonBE
    } yield s"$x + $y"

    val content = div(
      buttonA,
      buttonB,
      br(),
      label("response: "),
      child.text <-- c
    )

    val containerNode = dom.document.getElementById("main_content")
    render(containerNode, content)
  }
}

 

설명

  • for-comprehension 의 경우 buttonA event 가 있고 난 다음에 buttonB event 가 발생해야 c 값이 emit 된다. 순서도 중요하다. 특히, 첫 클릭으로 buttonB 가 클릭될 경우 아무런 event 도 전달되지 않는다. for-comprehension 을 flatMap 으로 변환해 보면 쉽게 이해된다. (debug 로그에도 안찍힘)
  • combineWithFn 의 경우는 buttonA, buttonB 클릭으로 양쪽 모두 적절한 값이 세팅된 상태일 때, 어느 하나만 클릭되어도 c 값이 emit 된다.

보통 기대하는 동작은 combineWithFn 이 될 것 같다.