Hi Vince,
Futures
A Future represents the completion of a computation.
computeFactorial := EsFuture on: [5 factorial].
You then chain together more tasks using #then:
Maybe in this example, after you have computed a factorial, then add 3 to the result.
computedFactorialPlus3 := computeFactorial then: [:factorial | factorial + 3].
You can keep going on and on, chaining together futures for complicated workflows, which is a heck of a lot nicer than lots of forks, semaphores and callback hell...especially when it involves exception handling.
Even more advanced usage such as the EsFuture class>>all: and EsFuture class>>any: is worth trying out.
Exception handling is another big win with the async framework.
There are also equivalents to the ensure: [] block as well.
Try the following.
future := EsFuture on: [Exception signal: 'Uh-oh'].
handledEx := future then: ["I never make it here"] catch: [:ex :st | ex inspect. st inspect].
complete := handledEx ensure: [Transcript show: 'I have finished'].
It's generally frowned on to add synchronous code to these workflows. That is why in Dart (from which this EsFuture/EsPromise framework was ported) it has no analog to blocking on waiting for a future completion.
However, I found it was necessary in the VAST environment, so I added it. You can add #waitFor to any future, and the current smalltalk process will block until its completed and answer the completion result of the future.
[complete waitFor.]
Promises
Promises are a great way to take synchronous code and create an asynchronous interface to it. Its usually used by the implementor side of the house.
In fact, I recently did an async version of SstHttpClient by subclassing it and using promises to create an async interface that returned futures and didnt' block.
| future promise |
promise := EsPromise new.
future := promise future.
future then: [:number | number inspect].
promise complete: 42.
The big win from these frameworks are with I/O.
When network and disk I/O is in involved, the asynchronous framework can help make your code dramatically more efficient.
The examples shown above don't really do it justice, but they are just simple examples.
A nicer example might do something like wrap an SstHttpClient fetch with it.
Something like
then: [:response | response inspect]
Be sure to read the method and class comments carefully. I tried to bring all the commenting over from Dart, and made the necessary
Smalltalk changes.
Let me know what other specific questions you have beyond these and I'll try and help. It is getting a little late for me so I was trying to keep it short for tonight:)
- Seth