Wes Higbee is passionate about helping companies achieve remarkable results with technology and software.
He’s had extensive experience developing software and working with teams to improve how software is developed to meet business objectives.
He writes extensively about both technical and non-technical aspects of software development at weshigbee.com
Wes skips the introductions and jumps straight into the questions:
- How will this plunk behave?
- Do you have a lot of experience working with other languages that are multithreaded?
- Have you ever thought about the complexity of the code that you’re writing and whether it might take up too many resources in the browser?
- Do you find callbacks confusing?
- Have you heard of event loops, run to completion, cooperative concurrency, and non blocking I/O?
If some of these questions are of interest to you, this could be the course for you.
Wes explains the objective of the course is to help us reason explicitly about when our code will run.
How to use this course
Wes stresses the importance of practicing and applying the lessons taught in this course. There are several challenges for you throughout the course to try out.
Links to Examples
- Avoid Blocking – Red background
- setTimeout Pyramid challenge
- Drag and Drop Red Box
- Timer onReady
- Timer measure
- Progress Number Crunching – Web Worker
- Event Listeners are Synchronous
You can also find links to these plunks at Wes’s Github Gist.
Many of the examples use Open Weather Map so it’s advisable to sign up for an account there if you don’t already have one.
Reasoning Explicitly About When Code Executes
Wes shows us the MDN article Concurrency Model and Event Loop, highlighting the second sentence:
This model is quite different than the model in other languages like C or Java.
Experience working with other languages can give us a “multithreaded mentality”.
We look at the weather plunk. They is quite a lot of code here, but the heart of it, and the most important part to focus on, is the load function.
This plunk runs quickly despite all being on on the same thread. This is due to the use of callbacks which allow us to continue running the rest of our code before we get the results of other code.
For example we make a weather request before our 5 day forecast request, but we don’t need to wait for the results of our weather request before we can make our 5 day frecast request.
How is this possible? We can get some clues by opening the Network tab in our browser’s Network tools.
Wes filters the timeline down to only show the web requests. They’re executed at the same time.
How to Avoid Blocking
weatherRequest.open('get', weatherUrl, true);
Look at the XMLHttpRequest.open documentation on MDN. The 3rd argument specifies whether it is asynchronous.
Wes demonstrates the effect of the flag by adding console.log statements and showing the order of execution with this flag on and off.
Run to Completion
This uses the avoid blocking plunk, the same example Wes begun the course with.
The key takeway (other than not to hog the bathroom) is the event listener runs to completion. This makes it especially important to not write long running code here.
Wes also returns to the weather plunk to explain the code execution in more detail.
Challenge – Run to completion
After discussing the weather plunk some more, we look at the setTimeout pyramid challenge.
Wes highlights this article and in particular the image of everyone waiting in line and unhappy outside the DMV.
Again see this MDN article for further details.
Animated Walkthrough of When Code Executes
Back of the Weather plunk again, or rather a subset of it.
Wes talks through the hypothetical execution of this program, covering:
- the Event Loop and its Queue
- the Call Stack and the code executing on it
- the Button Clicked event, load method, console.log, send weather etc.
Wes says the browser can have multiple threads executing multiple requests at the same time.
Mentality: Little Programs
In this lesson he illustrates each function as a little programs, and these are the asynchronous seams inside of our application.
Exercises and Examples
Sources of Async
We learn that the sources of asynchronicity include:
- User Interactions
- Network I/O
- Disk I/O – reading and writing files
- Inter Process Communication e.g. communicating back and forth with Web Workers
The following lessons demonstrate each of these.
Exploring the Drag and Drop – Red Box plunk.
Drag and Drop is an HTML5 feature that is not available in all browsers.
This plunk has console log messages so we can see which functions are getting executed and when.
How many “little programs” are involved in this example? Have a think about it, and then watch this clip for the answer.
Wes shows us the MDN setTimeout and the Node Timers API documentation.
With Node JS there are new ways to schedule timers.
There’s no guarantee of when functions inside of setTimer are executed – it all depends on the other work that is already sitting on the queue at the point where our function is added onto the end of it.
Timer Delay Gotchas
Our timer measure plunk measures the difference in time between the requested delay and the actual average delay. We can change the number of repetitions, and the requested delay in milliseconds, and observe it’s effect.
The shortest possible delay is 4 milliseconds, so anything less than that will actually mean 4 milliseconds.
This example uses ES6 syntax, so it won’t work in older browsers.
How many little programs in the timer measure plunk? The answer may bend your mind a little bit.
Not Always Async
A couple of trick questions from Wes as he asks us how many little programs, and how will the program behave? There is no way that we can tell!
Then we see the complete code listing. Does it make sense to you now? Things aren’t quite what they appear to be.
Wes updates the code so that it behaves asynchronously.
The key point is to remember to verify your assumptions when reading code.
Wes returns to the weather plunk once more and shows us how to use debugging as a tool for figuring out where all the asynchronous seams, (“little programs”) exist.
This makes use of the browser’s Call Stack and many break points.
Debugging with Async Call Stacks
Chrome Dev Tools has a relatively little known checkbox labelled Async.
Wes shows us how this works, and we see additional information in the Call Stack – where our asynchronous calls have come from.
This example uses Node JS. How many little programs are there?
Callbacks are a notorious sign that a function is asynchronous in Node JS, but we cannot just assume that. We should check the documentation where it exists, or reason about the code if it does not.
Node JS nextTick and setImmediate
There is good documentation available for these API functions:
We see a demonstrations of these functions and their effects.
Wes shows an example with a blocking resource, giving an awful user experience: we see the UI appear after more than 10 seconds.
It’s because, as we learned earlier, the blocking function needs to run to completion before the rest of the code can execute.
We can get a better understanding of how this code works by adding the console.log statements, and we see that at least in Chrome, logging to the console is not blocked.
Now with a few tweaks to this code, splitting it out into background.js and crunchNumbers.js, we get the progress bar working entirely as we want it to.
We see that using Web Workers is much more straightforward than writing asynchronous code in some other languages.
Back to the weather plunk again.
We see Race conditions can still happen because the order of items in the queue is not guaranteed.
Event Listeners are Synchronous
In this final example, we see two event listeners applied to the same button, and the results may be different from what we expected.
Wes steps through it in the debugger explaining how the code works.
Wes reiterates all the main points we learned in this course.