For a page with a few <script> tags that cause external files to be loaded and executed, there can be significant delays in site load times. That’s why if you run your site through Google’s PageSpeed Insights, it will complain about render-blocking JS.
One way of dealing with blocking JS is to move <script> content out of the page’s <head> section and put it at the end of the page. If we do that, JS won’t block the rendering of most the page, but it’s not a very good solution: the page will still freeze while the JS loads, although at least the user will have something to look at in the meantime.
By adding the Async attribute to <script> tags, you instruct the browser to go about things a little differently and load scripts asynchronously.
Once again imagine you’re a browser that comes across a <script> tag that loads an external file, only this one has the “async” attribute. This time, while you are downloading the file, instead of stopping dead in your tracks, you continue to parse the HTML. When you have the JS downloaded, you stop parsing the page and execute it.
Async minimizes the delay caused by JS loading, but allows it to execute as it normally would.
Which should you use
You should almost always use the “async” attribute, unless the script in question depends on another script or another script depends upon it. With “async” you can’t be sure when exactly the script will be executed because loading times are not predictable: “defer” allows you to make sure that the scripts always execute in the same order.
You should also keep in mind that “defer” support is spotty among older browsers, so if you have to support a creaky version of IE, it’s best avoided.