【问题标题】:Is it sensible to memoize promises?记住承诺是否明智?
【发布时间】:2015-07-28 13:32:00
【问题描述】:

我正在使用 HTTP Kit 发出请求,我希望它们是异步的,但我也想缓存响应。我希望请求是异步的的原因是我正在同时发出几个请求并且我希望它们并行运行。

这是我的函数,它同时发出多个请求。

(defn parallel-requests-1 [urls]
  (let [; Dispatch all requests to run concurrently.
        responses (doall (map #(http/get %) urls))
        ; Realise all promises.
        realised (doall (map deref responses))
        ; Extract response body.
        bodies (map :body realised)]
    bodies))

(parallel-requests-1 ["http://example.com", "http://example.net"])

这纯粹是为了说明目的,以证明我不想只是 deref 承诺并记住它。

现在我想使用memoize 添加缓存。我试过这个:

(def memoized-get (memoize http/get))

(defn parallel-requests-2 [urls]
  (let [; Dispatch all requests to run concurrently.
        responses (doall (map #(memoized-get %) urls))
        ; Realise all promises.
        realised (doall (map deref responses))
        ; Extract response body.
        bodies (map :body realised)]
    bodies))

所有迹象都表明这很有效。

这是一个明智的解决方案吗?我担心缓存承诺可能会造成某种资源泄漏。

【问题讨论】:

  • 记忆承诺比记忆值更明智,因为这样你就没有竞争条件,以防有人多次触发操作,因为记忆将在操作开始时发生而不是结束的时候。
  • 此外,缓存的 promise 将包含比其结果更多的信息。如果被拒绝,它将让您了解拒绝的原因,这在某些情况下可能很有用。例如,如果远程服务不可用,您可以选择重试,但如果原因为空结果,则不重试。或者您可能只是想记录/显示原因(再次)。
  • Promise 确实已经记住了它们的结果——我不清楚你希望通过调用 memoize 来实现什么。
  • Promises memoize 自己的结果,但是对http/get 的调用每次返回不同的promise,因此会产生一个新的请求。我想缓存http/get 的结果,即存储每个结果承诺。

标签: clojure promise core.async


【解决方案1】:

是的,记住一个承诺是明智的。事实上,在这种情况下,这可能是最明智的解决方案。毕竟,这就是http/get 返回的,这就是你要记忆的函数。

就资源泄漏而言,无论您记住承诺还是它的价值,这都不是问题。一个promise 基本上只是一些在deliver!ed 后引用值的状态。因此,您对这个参考有一点点开销,但与整个响应相比,它是微不足道的。

【讨论】:

  • 非常感谢。过去我的chans 供应有限(当我尝试创建太多时线程刚刚阻塞),所以我想确定一下。到目前为止,我在缓存 Promise 时没有遇到任何问题(尽管只有一天)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 2015-07-25
  • 2020-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-01
相关资源
最近更新 更多