3

语境

我正在使用 ClojureScript,所以 Ajax 对我的工作方式如下:

(make-ajax-call url data handler);

处理程序看起来像:

(fn [response] .... )

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

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

现在,我宁愿把它写成:

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

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

问题

有没有办法通过单子或宏来完成这项工作?这样 [2] 会自动重写为 [1] 吗?我相信:

  • 不会有性能惩罚,因为它被重写为 [1[
  • 我可以更清楚地推理,因为我可以以同步步骤而不是异步事件来思考

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

谢谢!

4

4 回答 4

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

于 2013-10-18T10:45:05.270 回答
1

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

于 2012-06-25T06:41:04.720 回答
1

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

于 2012-06-23T18:24:32.370 回答
1

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

(->> update-sidebar! (make-ajax-call "/fetch-new-data" {}))
于 2012-06-23T18:24:37.803 回答