Transactional composition.

Run each set of related asynchronous compositions in a transaction with a unique id.
Each transaction would have it's own compositionComplete instead of a system-wide compositionComplete callback.

In my case this was a requirement as we run many individual and unrelated compositions concurrently. In our case sometimes a single global compositionComplete does not make sense or results in undesired results as it does not correctly reflect the state of the system regarding composition of all widgets that are currently composing. It just says that at this mement there is no more running compositions but there might be some others which are not yet started!
On the other side this means that widget A should wait for widget B (which does not have anything to do with A) to finish its composition until A's compositionComplete is called.