|What Is Asynchronous Programming?|
|Written by Mike James|
|Friday, 04 March 2022|
Page 3 of 3
This idea that a function might not know what to do after it finishes its task can be solved in many ways but they are nearly all variations on the idea of continuation passing - i.e. passing an explicit something to do when the function has finished.
The simplest and best know of these approaches is to pass a call back function to the non-blocking function that contains the code that is to be executed when the task is complete.
The onCompletion function is called when getWorkDone has finished. Notice that onCompletion looks a lot like an event handler and in fact there is very little difference. A call back function is just an event handler that responds to the completion of the non-blocking function. You could adopt a different syntax that allowed the assignment of a callback as if it was an event. For example:
Event handlers tend to be called repeatedly when the event is raised but callbacks tend to be related to one off events like a file finishing downloading.
Of course things are a little more complicated in that this sort of mechanism seems to modify the natural logic of a function. A function that was:
is distorted into:
and while this example may not look so bad the reality is usually much worse.
You might think of a function as loading an image, processing the image and then displaying it but you have to convert into a function that starts the download and an event handler that reacts to the completion of the download.
In practice a function could be decomposed into many event handlers or call backs each dealing with the completion of some non-blocking function or other.
Dealing With Async
Given that asynchronous coding is so prevalent what can we do to make it better.
First we need to try to explain what makes it worse.
Writing a collection of event handlers generally isn't a difficult thing to do and with the condition that they all return fast there isn't really any difficulty.
Event handlers tend to be self contained and one event handler isn't in any way a continuation of another.
Where things get difficult is when you make use of a lot of non-blocking functions to make sure that event handlers return fast. The problem here is that calling non-blocking functions means passing call backs or completed event handlers depending on how you want to look at it.
This is fine when you are only calling one non-blocking function to get a task done but this is usually not the case.
Typically you need to perform a number of tasks and if the functions are blocking you might write:
To convert this to a set of non-blocking functions would result in something like:
where it is assumed that each function is passed a callback as its only parameter. That is each function is passed a function which calls the next function in the sequence. Function A calls function B when it is finished and Function B calls function C when it is finished.
This pyramid of doom style callbacks gets much worse in practice.
For the final example consider a loop:
and now convert it into a non-blocking call:
Assuming that funcA takes a callback as its second argument. Yes that's correct an enumeration loop turns into recursion with non-blocking calls.
However even this isn't the most general case. In this case the function called by the loop don't depend on each others results - if they do then you have
There are lots of other problems - handling error conditions, dealing with exceptions, conditional execution and so on.
All in all asynchronous programming using callbacks in non-blocking functions isn't easy.
The problem is that writing an algorithm in asynchronous non-blocking style completely destroys the natural logic of the task as expressed in a synchronous blocking form.
Are there any solutions?
Yes - see Promises, async and await, yield and any number of flow of control libraries that convert the convoluted callback structure into something more familiar.
We will take a look at these solutions in the second article.
or email your comment to: firstname.lastname@example.org
|Last Updated ( Friday, 04 March 2022 )|