...
| Code Block |
|---|
(defn do-operation [tries]
(if (zero? tries)
(throw (ex-info "Operation failed" {}))
(-> (future ...) ; long operation which may fail
(then value ...) ; handle success
(recover ex ; handle failure with retry
(do-operation (dec tries))))))
(do-operation 3)
|
Java Interop
Promises implement java.util.concurrent.Future. Extending them to similar APIs such as Guava's ListenableFuture is trivial.
Cancellation
There is no API to remove or cancel a callback created with attend. Instead, the then macro returns a promise which receives return value of the return value of the callback function. If you However, it is possible to deliver a value to that returned promise the promise returned by the then macro before the underlying promise is delivered. In that case, the callback function will not be executed. There is an implicit race condition with cancellation, so this cannot guarantee that the callback function will never be executed at all.
Futures can still be cancelled with future-cancel, which attempts to stop the Future's thread.
Calling future-cancel on a promise is equivalent to calling fail with an instance of java.util.concurrent.CancellationException.
Progress Reporting
Promises do not provide an API to report partial progress during a long-running operation. Progress reporting can be handled through other means such as watches.
ClojureScript
Promises can be implemented in ClojureScript, subject to the following limitations:
- There is no notion of executors
- Callbacks execute either synchronously or asynchronously (e.g., with
setTimeout) derefon an unrealized promise cannot block; instead it throws an exception
Discussions
- Promise/Futures with callbacks (Clojure-dev group)
- lamina and channels-driven concurrency with clojure (Clojure group)
- reactive programing (dev.clojure.org)
- can a better Future be exposed by API? (Datomic group)
...