Clojure(脚本):用于同步思考异步操作的宏

3

背景

我正在学习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 调用会立即返回。
问题
通过单子或宏的某种方式使其工作的方法是什么?这样 [2] 就能自动重写成 [1]。我相信:
- 由于它被重写成 [1],所以不会有性能惩罚。 - 对于我来说更容易理解,因为我可以思考同步步骤而不是异步事件。
我怀疑我不是第一个遇到这个问题的人,如果这是一个众所周知的问题,那么“Google 搜索 Problem Foo”这样的答案是完全有效的。
谢谢!

嗨,user1383359!我的答案(与核心异步相关)是否帮助您解决了这个问题?我尝试了一下,它非常有效。 - tangrammer
这篇文章特别涉及核心async和执行ajax调用的相关内容。http://dimagog.github.io/blog/clojure/clojurescript/2013/07/12/making-http-requests-from-clojurescript-with-core.async/ - tangrammer
4个回答

2

自从2013年6月28日发布clojure core.async库以来,你可以以更或少的方式完成它,如下所示: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
一个宏可以改变代码的外观,同时保持Ajax调用异步。这是一个简单的模板宏。另一种方法是将make-ajax-call的调用包装在等待结果的函数中。虽然这两种方法都可以工作,但它们可能看起来有点笨拙和“非Ajax风格”。额外的抽象层是否值得带来好处?

1

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

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

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接