Ross Esmond

Code, Prose, and Mathematics.

portrait of myself, Ross Esmond
Written — Last Updated

Future

A type representing a value which is expected to arrive at a later time. In Javascript these are called Promises. In C# they’re Tasks. Haskell uses Monad’s to handle future values. A future might also be used to represents an operation that is expected to finish at some definite time, but will not return a value. Futures also account for failure. In success or failure, the future is finished, and can no longer succeed or fail.

Code with access to the future may register handlers for both success and failure. These handlers can either cause a side effect, or proxy into another future. When the completion of a future is intended to trigger the creation of a new future, the new future is created now. This is an odd mechanic, but imagine a request to one server to get an id, which is then going to be used to request a resource on a different server. We know the entire process right now, so we request the id and create a future for the eventual result. We then subscribe to the success of the first future so that we may request the resource. When the id is eventually returned, we request the resource, get a future for the request, and we must now subscribe to the second future in order to perform whatever operation we originally intended. This is a clunky process, however, as the event handlers are now nested inside each other.

getId().then(id => {
    getResource(id).then(resource =>{
        doStuff(resource);
    })
})

We know the entire process from start to finish, so we should be able to codify the entire process now, and receive a promise for when the entire chain is done. This would allow our code to avoid nesting, as a function wrapper wouldn’t be required to delay execution. Javascript promises allow for this.

getId()
    .then(id => getResource(id))
    .then(resource => doStuff(resource))

getId returns a promise. When we call then on a promise, we pass in a function, and we get back a new promise. When the first promise succeeds, the resulting value will be passed into the provided function, and the new promise will succeed with that return value.

If, however, the return value is another promise, the new promise with succeed whenever that other promise succeeds with whatever value that other promise results in.