【问题标题】:Getting most recent response from a core.async从 core.async 获取最新响应
【发布时间】:2014-07-31 15:24:17
【问题描述】:

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

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

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

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

如果不是,core.async 是否可以做到这一点,我获得有序响应的最佳方法是什么?

谢谢

【问题讨论】:

  • 验证是否会重新生成将写入错误的通道?您能否详细介绍一下验证的工作原理?

标签: clojure clojurescript core.async


【解决方案1】:

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

顺便说一句,内部go 表单没有任何作用,可以合并到外部go-loop。 (好吧,go 形成返回通道,但如果 go-loop 实际上是要循环的,这可能并不重要。)

【讨论】:

  • 进一步回答这个问题,如果将验证服务建模为一个通道,在该通道上放置标记值以及从哪个类似标记的错误数组(可能为空) 被拉?
【解决方案2】:

你可以写一个开关函数(受 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 不处理关闭通道。

【讨论】:

    猜你喜欢
    • 2021-12-27
    • 2023-03-19
    • 2022-06-28
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多