Clojure(脚本):用于同步推理异步操作的宏

时间:2012-06-23 16:16:45

标签: clojure clojurescript

上下文

我正在玩ClojureScript,因此Ajax对我的工作方式如下:

(make-ajax-call url data handler);

其中handler类似于:

(fn [response] .... )

现在,这意味着当我想说“获取新数据并更新左侧边栏”时,我的结局看起来像:

(make-ajax-call "/fetch-new-data" {} update-sidebar!) [1]

现在,我更愿意将其写成:

(update-sidebar! (make-ajax-call "/fetch-new-data" {})) [2]

但它不起作用,因为make-ajax调用会立即返回。

问题

有没有办法通过monad或宏来实现这项工作?那么[2]被自动重写为[1]?我相信:

  • 不会有表演性,因为它被重写为[1 [
  • 因为我可以用同步步骤而不是异步事件来思考,所以我更清楚了解

    我怀疑我不是第一个遇到这个问题的人,所以如果这是一个众所周知的问题,那么“Google for Problem Foo”形式的答案完全有效。

谢谢!

4 个答案:

答案 0 :(得分:2)

自2013年6月28日clojure core.async lib发布以来,你可以用这种方式或多或少地做到这一点:https://gist.github.com/juanantonioruz/7039755

这里粘贴了代码:

(ns fourclojure.stack
    (require [clojure.core.async :as async :refer :all]))

(defn update-sidebar! [new-data]
  (println "you have updated the sidebar with this data:" new-data))

(defn async-handler [the-channel data-recieved]
  (put! the-channel data-recieved)
  )

(defn make-ajax-call [url data-to-send]
  (let [the-channel (chan)]
    (go   
     (<! (timeout 2000)); wait 2 seconds to response
     (async-handler the-channel (str "return value with this url: " url)))
    the-channel
    )
  )

(update-sidebar! (<!! (make-ajax-call "/fetch-new-data" {})))

更多信息:
* http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
* https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj

答案 1 :(得分:1)

宏会改变代码的外观,同时使Ajax调用异步。 这是一个简单的模板宏。另一种方法是在等待结果的函数中包含对make-ajax-call的调用。虽然这些中的任何一个都可以起作用,但它们看起来有点尴尬和“不像ajax”。这些好处值得额外的抽象层吗?

答案 2 :(得分:1)

使用线程宏怎么样?还不够好吗?

(->> update-sidebar! (make-ajax-call "/fetch-new-data" {}))

答案 3 :(得分:1)

我们在async branch跷跷板中对此有了粗略的想法。特别参见seesaw.async命名空间。