Asaps are very similar to promises, with two major differences:
- They can be resolved in the same thread.
- They can be cancelled
But other than that are fully compatible with promises
One of the main drives to create the ASAPs was to have an abstraction that will encapsulate promises, but that would also run them synchronously when possible.
Let's illustrate this with an example:
var thePro = new Promise ((resolve) => resolve(5));
thePro.then ((value) => console.log(value))
//This will print
As you can see, the promise resolves immediately, but the order of the execution is not what you might expect.
Every time you use a promise, the code to resolve the promise will be run as if it was in a different not concurrent thread
Let's compare it with an Asap.
var thePro = Asaps.now(5);
//This will print
In here, the Asap resolves, well.. asap
The goal is to simplify writing code that sometimes should resolve now, sometimes should resolve later...
If you are familiar with other state management frameworks like Redux, you might be a know a side effect of this, when you perform a synchronous operation that changes the state, but you can't query the state immediately after.
This small inconvenience then starts leaking all over the framework, all of the sudden you have to write callbacks for everything to guarantee that the state you want to read is up to date.
With ConanJs you will be able to query directly the state after performing an action that updates it synchronously. This is because ASAPs are used behind the scenes.
You can create an Asap through the Asaps class. In here you can find its main 3 methods.
If you have a promise, all you have to do is use this method to create an Asap from it.
let myAsap = Asasp.fromPromise(myPromise)
Lets you create a promise that resolves now to a value
let myAsap = Asasp.now(5)
Lets you create a promise that will be resolved synchronously, but it also lets you defer the value to resolve later on the same thread.
This method is the cornerstone of the reason of Asaps to exist, let's illustrate this with an example.
// returns a tuple, the first value is the atual asap
// the second is a function to resolve the value
let [asap, next] = Asasp.next()
// This will print
Asaps have a life cycle that matches the one for promises, with the added state of the Asap being cancelled.
Note that it is out of the scope of this documentation to explain how a promise works, so we are going to assume that you are familiar with them.
The two main life cycle methods for a promise are then and catch, in ConanJs we also have onCancel.
Similar to a normal promise, you can append listeners to execute once that the promise is resolved successfully.
These listeners will be executed in case of an error triggered while resolving the underlying Asap.
Lastly, you can also add listeners to be executed when the promise has been cancelled.
As of v1.0 we don't have a finally callback, but this would be added soon.
Whether a promise should be cancellable or not will likely spark flame wars, and we do understand why:
- If you cancel an async operation, but you don't cancel everything that operation has started, can it really be cancelled?
- How do you cancel a network call already started?
These are very difficult questions to answer and they have stalled any potential progress into providing this mechanism built in for Promises.
But we think that this is not fair for the developer, that an operation is dangerous and delicate, should not mean that is also very complicated to trigger.
Would this mean that is going to cancel everything that you started? NO
You will need to make sure that you react to the cancellation according to your business use case, and do as much housekeeping as needed, but at least you get to choose if you want to go down this route.