ASAPs

Introduction

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

Synchronous Execution

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))
console.log('hi!')

//This will print
//hi!
//5

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);
thePro.then ((value)=>console.log(value))
console.log('hi!')

//This will print
//5
//hi!

In here, the Asap resolves, well.. asap

Why?

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.

Creating ASAPS

You can create an Asap through the Asaps class. In here you can find its main 3 methods.

To see all the available methods, like resolving an Asap on the back of a fetch check the Asaps API docs.

fromPromise

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) 

now

Lets you create a promise that resolves now to a value

let myAsap = Asasp.now(5) 

next

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() 

console.log(1)
asap.then((value)=>console.log(value))
next(2)
console.log(3)

// This will print
// 1
// 2
// 3

Life Cycle Interface

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.

then

Similar to a normal promise, you can append listeners to execute once that the promise is resolved successfully.

catch

These listeners will be executed in case of an error triggered while resolving the underlying Asap.

onCancel

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.

Cancelling Asaps

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.

That is why we provide with asap.cancel (). if you call it, it will not resolve (then and catch will not be invoked), and instead all onCancel listeners will be invoked.

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.

Last updated