(def p (promise))
(future ;; some other thread starts working with the promise
(Thread/sleep 500)
(deliver p :finished-early))
(deref p 1000 :timed-out) ;; => :finished-early
Run Code Online (Sandbox Code Playgroud)
如果睡眠花费的时间超过了1000那么deref就会回来:timed-out.
更新:我现在看到你的问题更具体地说是原子.在这种情况下,您仍然可以通过在原子上添加监视来使用promise,并在值发生更改时传递promise:
(def p (promise))
(def a (atom {}))
(add-watch a :watch-changed
(fn [_ _ old new]
(when-not (= old new) (deliver p :changed))))
(future
(Thread/sleep 1001)
(swap! a assoc :foo 1))
(deref p 1000 :timed-out) ;; => :changed
Run Code Online (Sandbox Code Playgroud)
或者在可重复使用的函数形式中,r可以是任何IRef类型:
(defn await-change [r timeout-ms]
(let [p (promise)]
(try
(add-watch r :await-change ;; keyword must be unique per ref!
(fn [_ _ old new]
(when-not (= old new) (deliver p :changed))))
(deref p timeout-ms :timed-out)
(finally
(remove-watch r :await-change)))))
(def a (atom {}))
(future
(Thread/sleep 500)
(swap! a assoc :foo 1))
(await-change a 1000) ;; => :changed
Run Code Online (Sandbox Code Playgroud)