Callbacks, Promises and Await
Synchronous programming is easier for most people to grasp. Commands execute in order, one after the other. Unfortunately the real world is not so straightforward. Many things are happening at the same time. We may not be able to predict when an event will occur, or how long it will take.
We don’t want our computer to freeze up when, for example, we are waiting to connect to a Bluetooth device. Instead, we initiate the connection and write a seperate function that will be executed after the connection has been established.
Traditionally this would be achieved by passing a “callback” function as a parameter to the function that initiates the connection.
asynchronousTask(function() {
// Task complete
});
However, for a multi-step process (e.g. connecting to a Bluetooth device, connecting to a service, reading a characteristic) code can quickly get messy and difficult to debug as the number of callback functions grows.
asynchronousTask(function() {
// First task complete
anotherAsynchronousTask(function() {
// Second task complete
yetAnotherAsynchronousTask(function() {
// All done!
});
});
});
Promises were designed to address this issue. After the first function, we call then() on the result, passing the second function we want to execute. We can chain as many steps together as we need. Promises allow us to more clearly write multiple step asynchronous processes.
asynchronousTask()
.then(anotherAsynchronousTask)
.then(yetAnotherAsynchronousTask);
Things can still get a bit ugly when we rely on data returned from a promise to be fed to the next task.
asynchronousTask()
.then(function(result) {
return anotherAsynchronousTask(result)
})
.then(function(result) {
return yetAnotherAsynchronousTask(result)
});
Finally we have async and await, which turn a normally asynchronous function into a synchronous one. Granted this is not always what we want, it does simplify things. Our code will stop and wait for the result of each task.
async function formallyAsynchronousTask() {
var result = await asynchronousTask();
result = await anotherAsynchronousTask(result);
await yetAnotherAsynchronousTask(result);
}