从core.async获取最新响应

时间:2014-07-31 15:24:17

标签: clojure clojurescript core.async

我试图通过每次表单更改时向验证函数发出请求来使用core.async验证表单。验证功能本身是异步的。它命中外部服务并返回错误消息数组或空数组。

(go-loop []
   (when-let [value (<! field-chan)]
      (go (let [errors (<! (validate value))]
             (put! field-error-chan errors)))))

上面的代码就是我现在所拥有的。它大多数时间都有效,但有时来自服务器的响应时间会发生变化,因此第二个请求会在第一个请求到达之前到达。如果该值在第二种情况下无效但在第一次有效时我们将从字段错误-chan中拉出一个错误数组后跟一个空数组。

我当然可以从go循环中取出验证并让所有内容以正确的顺序返回,但是,我会在检查错误后最终从field-chan中获取值。我想要做的是验证值的来源,但是将验证响应放在错误通道上,其顺序是值不是响应的顺序。

如果不是获得有序响应的最佳方法,那么核心.async是否可行?

由于

2 个答案:

答案 0 :(得分:1)

假设您可以修改外部验证服务,最简单的方法可能是将时间戳(或简单的计数器)附加到验证请求,并让验证服务将它们包含在响应中。然后你可以随时告诉你是否正在处理对最新请求的回复。

顺便提一下,内部go表单没有用处,可以合并到外部go-loop。 (好吧,go形成了返回通道,但是如果go-loop实际上是为了循环,那么这可能并不重要。)

答案 1 :(得分:0)

你可以写一个开关功能(灵感来自RxJs):

(defn switch [in]
  (let [out (chan)]
    (go (loop [subchannel (<! in)]
      (let [[v c] (alts! [subchannel in])]
        (if (= c subchannel)
          (do (>! out v) (recur subchannel))
          (recur v)))))
    out))

然后包装field-chan函数和

(let [validate-last (switch (async/map validate [field-chan])]
  ...)

但请注意,switch无法处理关闭渠道。