Important Notice
In this version, one of the problems that existed since the birth of this library has been corrected, related to the fact that the default implementation of js/Promise makes it impossible to nest promises. This fact has caused the library in the first place to have had a divergence with its counterpart in CLJ/JVM and, secondly, to the fact that mapcat-type operators could not be correctly implemented, making them practically useless.
With this version, the problem is fixed and while it cannot technically be considered a backwards compatibility break, some operators with promises will not function identically. Basically the magical auto-unwrapping of promises is gone.
Function docstrings have already been explicit about what they are expected to return, so if you've been relying on the js/Promise implementation detail in CLJS, it's possible that some pieces of code are broken, because now several operators already work the same way in CLJ and CLJS.
It should be said that only a set of operators has been really affected by the change. The Promise library exposes two styles of APIs:
->
(then
, catch
, handle
, finally
)
macro and is intended to emulate the behavior of js/Promise and that api hasn't changed,
keep going working as it worked;->>
macro (the fmap
,
mcat
, hmap
, hcat
, merr
and fnly
functions, where already the contract was more
strict); This is where this fix may have really affected the most since it makes it even
stricter regarding the return values of the callbacks. As I have already commented
before, the docstrings already had all this specified for a few versions.Breaking changes:
:async?
to :async
prop on fork-join-executor
for naming consistencyRelevant changes:
pending?
done?
resolved?
and rejected?
predicates to be used from CLJSIDeref
implementation to promises (@promise
or (deref promise)
now can be used
on CLJS in a nonblocking way, if promise is not fulfilled, nil
will be returned)promesa.exec/get-thread-id
as replacement for the deprecated thread-id
function.promesa.exec/fn->thread
thread constructorpromesa.exec/thread-call
thread constructor (advanced version of
promesa.core/thread-call
) that creates unpooled threadspromesa.exec/set-name!
helper for set/update thread namepromesa.exec/get-name
helper for retrieve thread namepromesa.util/try!
macro helper that wrap expression into a try/catch block and
return the result or exception as valuepromesa.util/ignoring
macro helpet that wrap expression into a try/catch block and
return the result or nil
if exception is raisedpromesa.exec.semaphore
(only on JVM) namespace with helpers for working with
Semaphore instancespromesa.exec/thread
low-level macro.once-buffer
(analogous to core.async promise-buffer
).expanding-buffer
as more flexible alternative to fixed-buffer
.expanding-buffer
by default on channels initialized with
buffer size.then'
and chain'
promesa.core/wait-all
helperpromesa.exec.csp/mult*
alternative multiplexer constructor
more similar to the clojure.core.async/mult
onepromesa.exec/run!
and promesa.exec/submit!
; make them
respect the promesa.exec/*default-executor*
dynamic var value when
no explicit executor is providedpromesa.core/loop
macro (making
it a little bit more efficientpromesa.core/await!
and promesa.core/await
helpers that serves for blocking current thread waiting the
termination/completion of some resource; (EXPERIMENTAL, JVM
only, look at ref-docs for details). Implemented by default for
Thread
, CountDownLatch
, CompletionStage
and
CompletableFuture
.promesa.exec.csp/pipe
using promise API; removing
internal go-block and make it more friendly to non-vthread JVM.promesa.exec.csp/onto-chan!
using promise API;
removing internal go-block and make it more friendly to non-vthread
JVM.BREAKING CHANGE ON EXPERIMENTAL CSP API:
put!
as blocking API, and move future returning api to put
.take!
as blocking API, and move future returning api to take
.This release includes internal protocols changes that breaks compatibility. If you are using only public API, you should not be affected.
promesa.core/chain'
functionpromesa.core/catch'
functionpromesa.core/error
alias to catch
promesa.core/any
implementationpromesa.core/err
alias.promesa.core/hmap
and promesa.core/hcat
functions (in the
same family as promesa.core/handle
but with arguments in inverse order and no
automatic unwrapping)promesa.core/fmap
convenience alias for promesa.core/map
promesa.core/merr
(inverse ordered arguments and no automatic unwrapping
version of promesa.core/catch
)promesa.exec.csp/!<
arguments (thanks to @alexandergunnarson)promesa.exec.csp/go-chan
convenience macro (thanks to
@alexandergunnarson for the suggestion)promesa.exec/thread?
functionpromesa.core/mcat
, a shorter alias for mapcat
promesa.core/hmap
, a shorter alias for handle
with inverted
arguments (for ->>
)promesa.core/fnly
, a shorter alias for finally
with inverted
arguments (for ->>
)promesa.exec.bulkhead/bulkhead?
predicate.promesa.exec/interrupt!
function (interrupts the
current thread).BREAKING CHANGES:
They are very recent additions and may be considered experimental, but still worth mentioning as breaking change:
px/thread-interrupted?
to px/interrupted?
px/interrupt-thread!
to px/interrupt!
promesa.exec.csp/sleep
to px/sleep
Other changes:
px/shutdown?
predicatepx/sleep
accept number (in milliseconds) and duration instancepx/shutdown!
and px/shutdown-now!
CLJ onlypx/thread
macro parameterspx/thread
by default the daemon flag to truepx/current-thread
helper functionpx/thread-interrupted?
helper functionpx/interrupt-thread!
helper functionpx/join!
helper functionpx/thread-id
helper functionpx/thread
low-level macro for create non-pooled threadspmap
.with-dispatch
ConcurrencyLimiter
(java impl) with
Bulkhead
(100% clojure impl; cljs not suported but contributions
welcome to port it to cljs if someone consider it can be useful).promesa.core/wrap
; it now only wraps if the value is not a promise instancepromesa.exec/pmap
; a simplified clojure.core/pmap
analogous
function that allows use a user specified executor (thanks to the
dynamic vars) (EXPERIMENTAL)promesa.exec/with-executor
helper macro for easily bind a new
value to the *default-executor*
and optionally close it on lexical
scope ending (EXPERIMENTAL)Date: 2022-10-31
Date: 2022-10-31
Date: 2022-10-18
Date: 2022-10-17
Date: 2022-10-17
Date: 2022-10-17
-run!
protocol method be implemented in terms of -submit!
.Date: 2022-10-17
Date: 2022-10-15
pending?
impl in JVMDate: 2022-10-09
p/thread
macro, now it uses unbounded cached thread
pool instead of the default one.Date: 2022-10-06
Bug fixes:
default-forkjoin-thread-factory
to be defined (thansk to @mainej).Date: 20220-10-06
Changes promesa.core
ns:
thread-call
helper.thread
macro (analogous to the clojure.core.async/thread
)thread-call
function (analogous to the clojure.core.async/thread-call
)vthread
macro (only on JDK19 with Preview enabled).vthread-call
function (only on JDK19 with Preview enabled).future
and thread
macros aware of var bindings.create
promise factory catch all exceptions.Changes to promesa.exec
ns:
thread-per-task-executor
executor factory functon (JDK19 with Preview).vthread-per-task-executor
executor factory functon (JDK19 with Preview).Date: 2022-10-02
BREAKING CHANGES:
promesa.exec/counted-thread-factory
is renamed to
promesa.exec/default-thread-factory
and the call signature is
changed.promesa.exec/forkjoin-named-thread-factory
has is renamed to
promesa.exec/default-forkjoin-thread-factory
and the call
signature is changed.future
macro has changed to does not automatically unwrap
returned promises. This is change is motivated for make it behave in
the same way as clojure.core/future
as promesa.core/future
expects to be a replacement for it.Enhancements:
*-pool
executors constructors in favour of new
variants called with the same name and the -executor
prefix. The
new constructor functions are all uniform with call signature.doseq
(thanks to @borkdude).with-dispatch
macro.Bug fixes:
p/future
macro
trully cancellable.Date: 2022-02-24
with-redefs
macro to clj-kondo config (thanks to @eccentric-j)Date: 2022-02-23
promise?
to check for IPromise protocol instead of concrete types. Now it should
more easy extend promise to other promise like types.promise.core/do!
macro to promise.core/do
(backward compatible, previous
macro still in the codebase)with-redefs
macro (thanks to @eccentric-j)Date: 2022-02-22
promise?
to check for IPromise protocol instead of concrete
types. Because the impl was wrong.Date: 2022-02-22
promise?
to check for IPromise protocol instead of concrete
types.promesa.exec/with-dispatch
macro.Date: 2022-02-21
bind
function behave as it should behave (like bind and
not being then
alias). This is technically a breaking change,
the bind
function should have been implemented in terms of bind
operation and not be an alias for then
.Date: 2022-02-16
Date: 2022-02-12
as->
threading macro (thanks to @wilkerlucio)Date: 2022-02-03
->
and ->>
threading macros (thanks to @wilkerlucio)Date: 2021-06-01
timeout
internal timeout handling.Date: 2021-05-13
scheduled-pool
function.Date: 2020-10-01
Relevant changes:
Add missing -then
impl for default
object (fixes issues of
promesa.core/then
chain function with promises that does not
inherito from js/Promise
).
Remove already deprecated for a while the alet
alias to let
macro (the migration should be a simple find-and-replace).
Add forkjoin-pool and factory helpers to promesa.exec
ns.
Date: 2020-02-05
Relevant changes:
loop/recur
(make its scheduling extensible and by
default it uses the common thread pool for scheduling body execution
for prevet stack overflow).promesa.core/*loop-run-fn*
dynamic var for cases when you need
customize where the loop/recur body exection is scheduled.Date: 2020-01-10
Relevant changes:
catch
and handle
(enabling the same
semantic than then
function).catch'
variant for cases when you sure that funcion always
return a plain value (and not promise).promesa.core/plet
.promesa.core/let
with promesa.core/do!
macro.promesa.core/plet
with promesa.core/do!
macro.Date: 2019-10-03
Date: 2019-10-03
Date: 2019-10-01
Relevant changes (many breaking changes that affects functions and macros that are not heavily used):
Remove the ability to create a promise using factory function with
promise
constructor (now this responsability is delegated to the
create
function, see below).
Remove the old do*
macro.
Add do!
macro (that should have been the do*
from the
begining). It treats each individual expression as a expression that
evaluates to promise and executes serially awaiting each
expression. Returns a promise resolved to the result of the last
expression, ignoring all intermediate results.
(require '[promesa.core :as p])
(p/do! (expr1)
(expr2)
(expr3))
;; That is roughtly equivalent to:
(p/alet [_ (expr1)
_ (expr2)]
(expr3))
Refactor execution strategy: before this change all the chained
callback functions (with map
, then
, etc..) they were running in
a separated (async) microtask (forkJoinPool on the jvm). Now
promesa does not makes any asumption about this and delegate
this decision to the user of this library.
What are the implications for the end user?: In terms of api changes, nothing; all the public api is the same. The main change consists in the execution semantics. Now all the chained functions (by default) will be executed in the calling/resolver thread instead of a new task for each step. This will leverage a better performance and less latency on all chain execution.
Also, promesa exposes additional arities to map
, then
,
bind
and mapcat
for provide a custom executor service if you
need it.
The promise
and deferred
(read more below) promise constructors
also accepts a new arity for specify the executor where evaluate the
factory function or promise resolution (by default is in the calling
thread).
The execution semantic changes are only relevant on the JVM, on cljs nothing is changed.
Rewrite finally
function: now receives a promise and a function
(potentiall side-effectful) that will receive resolved value as
first argument if the promise is resolved or exception as second
argument if promise is rejected. The return value is ignored. It
always returns the same promise (like identity function).
Remove 0 arity from promise
function (now is delegated to deferred
)
Remove schedule
function from promesa.core
(replaced by promesa.exec/schedule
).
Remove extend-promise!
from promesa.core
(still available in promesa.impl
).
Remove set-default-promise!
helper (the user can do the same without the helper).
Remove attempt
function (not useful).
Remove branch
function (not useful).
New features and not breaking changes and fixes:
create
promise constructor, a facility for create a promise
using a factory function (before this is done passing a function to
promise
).deferred
promise constructor. The main purpose of this
constructor is creating an empty promise ready to be resolved or
rejected externally (using resolve!
and reject!
).handle
chain function: is some kind of combination of then'
and catch
. It chains a function to be executed when the promise is
either normally or rejected (with first argument with resolved value
(or nil) and second argument with the exception (or nil) if promise
is rejected). Returns the promise resolved with the return value of
the chained function. Does not flatten the result.then'
chain function. Is a variant of then
function that
does not flatten the result (a more performant variant).chain'
chain function helper. Is a chain
variant that does
not flatten the result (a more performant variant).alet
to let
(alet
is stil awailable as alias for
backward compatibility).plet
as syntactic abstraction/sugar for all
composition
operator.race
composition operator.run!
function (a promise aware run!
variant).promesa.exec
namespace with Executors & Schedulers abstractions.future
macro (analogous to clojure.core/future
that returns
promise instance instead of Future, also works in cljs) that uses
promesa.exec
behind the schenes.let
macro making it safe to synchronos exception that can
be raised from the first evaluated expression. Now all exception
raised inside let
returs properly rejected promise.loop/recur
syntax abstraction.Date: 2019-08-21
This is a breaking change release; even though the majority of public (not experimental) api is not affected. Relevant changes are:
promesa.async
and promesa.async-cljs
namespaces. They was
experimental and finally they don't demonstrate to be useful in
comparison to the complexity that they introduce.Other changes:
alet
macro implementation; it's no longer needs await
for wait promise binding resolution.Date: 2019-03-30
Yo now can create an empty promise (without a factory function) and
resolve or reject it using the new functions: resolve!
reject!
.
Example:
(require '[promesa.core :as p])
(let [pr (p/promise)]
;; do something
(p/resolve! pr 2))
Date: 2019-02-19
This is a breaking change release. Finally bluebird is gone in favour of using the ES6 builtin Promise object. This removes the overhead (in size) of the additional external library.
The reason of using bluebird initially was because native promises performed badly, but in new versions javascript engines the performance and memory usage is improved significantly. In any case you can still use the bluebird if you want, thanks to the new functions:
set-default-promise!
: enables the user setting up a custom promise
constructor as default one for promesa library.extend-promise!
: enables the user to use a custom promise
implementation with promesa library abstractions.Other (also probably breaking) changes:
timeout
is now implemented in terms of internal scheduler
facilities (bluebird impl was used previously) and it is now
available for clojure (jvm).any
is reimplemented in clj/cljs and now accepts an additional
argument for setting the default return value if promise is
resolved. If default value is not provided, an ExceptionInfo will be
throwed.Date: 2018-08-03
Date: 2017-04-20
_
character from internal assets directory. That fixes incompatibilities
with cordova/android build tools.Date: 2017-02-21
then
function on clj in respect to cljs.async
macro (on cljs).Date: 2016-12-18
finally
implementation.Date: 2016-11-02
async
macro that uses core.async
machinary in order to build go
like macro and allow to have fully async/await syntax.clj->js
and js->clj
functions.Date: 2016-08-18
Date: 2016-07-10
Date: 2016-06-08
Date: 2016-06-08
finally
combinator function.do*
promise constructor (analogous to Promise.attempt
).promise.monad
namespace.Date: 2016-05-20
Date: 2016-03-19
Date: 2016-03-18
err
and error
alias as catch
analougous function
that has the parameters inverted in the same way as map
and mapcat
.Date: 2016-03-17
map
function.mapcat
function.Date: 2016-02-13
Date: 2016-02-13
promesa.monad
ns.async/await
like syntax.Date: 2016-01-08
Date: 2015-12-03
Important changes:
Other changes:
Date: 2015-09-27
Date: 2015-09-18
then
combinator.-name
protocol naming convention.Date: 2015-08-18
Date: 2015-08-02
Date: 2015-07-18
Date: 2015-06-13
Date: 2015-05-16
Date: 2015-04-16
Date: 2015-03-28
Can you improve this documentation? These fine people already did:
Andrey Antukh & Alejandro GómezEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close