应对Bacon.js的副作用

时间:2014-09-16 21:42:00

标签: ajax coffeescript purely-functional bacon.js

我是Bacon.js的新手,通常在Haskell中编写程序。 根据我对Haskell的经验,我想将Bacon.js中的一些情况描述为纯粹的功能性方法。

以下是一个示例情况。

  • triggerStream是源流。
  • resultStreamtriggerStream事件发生时尝试访问ajax。
  • resultStream2在完成resultStream ajax访问后也会尝试访问ajax。

这是我的方法:

### =======
# Streams
# ======= ###
triggerStream = () ->
  Bacon.fromArray([1,2,3])

resultStream = 
  triggerStream()
    .flatMap((n) -> Bacon.fromPromise($.ajax(toAjax n)))
    .zip(triggerStream(), (r,t) ->
      {result: r, trigger: t}

resultStream2 =
  resultStream     # (*)
    .flatMap((o) -> Bacon.fromPromise($.ajax(toAjax2 o)))
    .zip(resultStream, (r2,r1) ->
      {result: r2, trigger: r1.trigger}

### =======
# Assignments
# ======= ###

triggerStream()
  .onValue(beforeAjax1) # (a)
resultStream
  .onValue(afterAjax1)  # (b)
resultStream2
  .onValue(afterAjax2)  # (c)

(a)支持在每次触发事件后执行,换句话说,它在resultStream ajax访问之前执行。

(b)支持在resultStream ajax访问后被解雇。

(c)支持在resultStream2 ajax访问后开始。

我知道Bacon.js的溪流或属性对自己有副作用,所以我的代码不能很好地运作。 在(b)中,resultStream的事件将从resultStream对象中删除,从而导致(*)中的空流。

resultStream更改为函数(如triggerStream)接缝的方法效果很好,但是当(b)和(b)和{b}时,它会导致resultStream ajax访问独立两次(c)中。

有没有想法实现我的方法?

1 个答案:

答案 0 :(得分:4)

问题在于您使用Bacon.fromArray作为来源。此方法返回一个同步响应的流,实际上将其内容吐出到第一个订阅者。

您可以尝试更实际的来源,例如Bacon.sequentially来完成这项工作。或者您可以stream.delay(0)将其更改为异步响应。

另见Bacon.js常见问题解答:https://github.com/baconjs/bacon.js/wiki/FAQ#why-isnt-my-subscriber-called