My grandfather loved watching westerns. He had shelves full of old VHS tapes, each meticulously labeled with a number, the contents of which were documented in a notebook perched atop a side table next to his chair. It was a common occurrence for my grandfather to doze off during an episode of Gunsmoke. Not realizing he was asleep, I would ask him some random question. In his half-daze, he would utter his witty reply – “Huh? Checkin’ for holes in my eyelids.” He didn’t know it at the time, but my grandfather was showing me how asynchronous tasks worked.
Much like grandpa didn’t let his experience of napping get interrupted by his side task of inspecting his eyelids, there are reasons and methods for employing async workflows in software engineering. I’ll provide a very basic primer on the why as well as the how of async so you can start thinking and applying async as an engineer.
Synchronous vs. asynchronous
Think of the difference between sync and async like the difference between a phone call and a text message, respectively. With a phone call, you call someone, wait for them to pick up, and when they answer, you start talking. When you send a text message, you type, send, and go about your business. The recipient of your message is free to respond whenever they are available.
Put another way, handling tasks synchronously means waiting. You issue a command to a machine, you wait, it responds. We do a lot of waiting when building solutions, like waiting for databases to save data or for HTTP requests to complete. Sometimes this is desired. You may want to wait for the result of a particular command. For example, if someone was signing in to your service, you would synchronously check to make sure they are authorized. When we write synchronous code, we’re waiting for things to complete in sequence. But what if we want to reduce the overall time to complete tasks? What about when you don’t want to wait? Or when you want to wait for some things, but not others?
Async task handling means you don’t have to, or don’t want to, wait for the results. It means you can multi-task, working on many things at the same time while waiting to hear back, resulting in lower overall execution time. One common use case for async is to provide a performant user experience. When a user signs up for a service, you want to give them access to your service right away, instead of first sending them a welcome email, and syncing up the data to your CRM, all before you let them in. Async tasks allow you to defer or offload these related and sometimes complex tasks.
Along the same lines, you should consider handling calls to third-party APIs using async. Minimizing any waiting for end users of your product should be a top priority. Latency and complexity of calls to third party services shouldn’t impact your core application and bubble up to end users. You can take advantage of your language’s async capabilities to keep your software performant.
How async is handled
Each language or framework has its own way of dealing with async, typically abstracting away the underlying machine operations. They provide an interface to write asynchronous code. Some have built-in capabilities, others rely exclusively on third-party libraries, and others have some combination of both.
- Callbacks: MDN: Declaring and using callbacks, Callback Hell
- Reactive, observables, state trees: RxJS, Redux, Introducing the Observable
Python added asyncio to the standard library in 3.4 and the async/await keywords in 3.5. It has also had frameworks like Tornado for some time. For python-sparkpost, we leave async up to the implementor, but a community member contributed a Tornado module.
- Async/Await: How the heck does async/await work in Python 3.5?, asyncio, coroutines
- Libraries: Tornado, eventlet, celery, awesome python (search the page for async)
There are a plethora of approaches and resources for async in PHP. I personally found the PHP Roundtable discussion on async in PHP to be a good overview for not only PHP, but async in general. There is an async-interop group working on async implementations and a proposal for PHP 7 for the PHP-FIG. Facebook created their own language and virtual machine that addresses async among other things. Our PHP client library uses the httplug library’s HttpAsyncClient and Promise classes.
What about my language?
A summary of the asynchronous features available in every language would make for a very long post and require frequent updates. Many languages are now either built with async in mind or have some form of async available as a first class feature of the language. Whatever language you use, a good old google search should get you a long way.
Determining when to use synchronous or asynchronous tasks, like much of engineering, can be an art. Handling tasks asynchronously allows you minimize the impact to the user experience, allows you to perform operations in parallel, and helps you scale by deferring or distributing heavy lifting. With the wide variety of tools and libraries now available, it’s easy to get started. In other words, this ain’t your grandpa’s async.
Want to talk more with our team and other SparkPost community members about engineering? Then hop into our community Slack and say hi.
–Rich Leland, Director of Growth Engineering